Jpa-2.0 – JPA – only the first submission fails, but all should fail

Please help me to explain the following (for me) very strange JPA behavior I deliberately change the primary key of entities prohibited in JPA

So first submit the correct exception Description: the attribute [date] of class [some. Package. Holiday] is mapped to the primary key column in the database. Update is not allowed

But the second (third, fourth,...) success! How is this possible?!

Holiday h1 = EM.find(Holiday.class,new GregorianCalendar(2011,3).getTime());

try {
    EM.getTransaction().begin();
    h1.setDate(new GregorianCalendar(2011,4).getTime());
    EM.getTransaction().commit();
    System.out.println("First commit succeed");
} catch (Exception e) {
    System.out.println("First commit Failed");
}

try {
    EM.getTransaction().begin();
    EM.getTransaction().commit();
    System.out.println("Second commit succeed");
} catch (Exception e) {
    System.out.println("Second commit Failed");
}

It will print out:

First commit Failed
Second commit succeed

God, how is this possible?!

(use eclipse link 2.2.0.v2011022-r8913. In MySQL.)

Solution

The failure of the commit operation of the first transaction has nothing to do with the second transaction This is because the entitytransaction is no longer active when the first commit fails When you issue the second em.gettransaction() When begin invocation, a new transaction that does not know the first transaction will be started

It is worth noting that although your code can use the same entitytransaction reference in both cases, this class does not actually have to represent the transaction For eclipse link, the entitytransaction reference actually wraps an entitytransactionwrapper instance that further uses repeatableunitofwork. The latter two classes are implemented by eclipse link rather than provided by JPA The repeatablewriteunitofwork instance actually tracks the set of changes made by entities that will be merged into the shared cache (and database) When the first transaction fails, the underlying unitofwork is invalid, and a new unitofwork is created when the second entitytransaction is started

The same applies to most other JPA providers because the entitytransaction class is not a concrete final class On the contrary, it is an interface usually implemented by another class in the JPA provider. It may also wrap a transaction, requiring the client to use the entitytransaction reference instead of directly using the underlying transaction (possibly JTA transaction or resource local transaction)

In addition, you should remember:

> EntityTransaction. Begin() should only be called once Calling it again will cause an IllegalStateException to be thrown because it cannot be called when the transaction is active Therefore, you can call it a second time, which means that the first transaction is no longer active. > If the changes you require to be performed in the context of the first transaction are available for the second transaction, you must merge the entities back into the shared context in the second transaction after the first transaction is detached Although this may sound ridiculous, you should remember that before merging, the client (read, end user) can modify the separated entity, so the changes made by the end user may be retained, and errors (such as modification) can correct the primary key during the transition

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>