Community
Participate
Working Groups
My code contains an entity with four associations (all lazy). It is used in the following call sequence: Entity e = new Entity(); // all associations are initialized with empty collections. em.getTransaction().begin(); em.persist(e); em.getTransaction().commit(); em.lock( e, LockModeType.PESSIMISTIC_WRITE); ... In v2.1.1 em.lock() caused one select for update. In v2.4 it causes four more selects - one for each association. This is a problem for me, because in this part of the code performance is critical. It looks like when calling lock(e) in 2.4 not only e is refreshed, but also all of the associations of e. It would be sufficient for me to just refresh e. Adding the QueryHint REFRESH_CASCADE=CascadePolicy.NoCascading to the call of em.lock() doesn't change anything.
It looks like ForeignReferenceMapping.buildCloneFromRow()together with ForeignReferenceMapping.valueFromRowInternal() are causing the additional selects. For each association ForeignReferenceMapping.valueFromRowInternal() returns a new IndirectList. ForeignReferenceMapping.buildCloneFromRow() later calls indirectionPolicy.instantiateObject() on the IndirectList which causes the additional select. From my point of view, at least with QueryHint.REFRESH_CASCADE=CascadePolicy.NoCascading, the methods should just clone the existing collection for each association, instead of replacing it with a new IndirectList(which is right after that loaded from the db).
Setting target and priority. See the following page for the meanings of these fields: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines Community: Please vote for this bug if it is important to you. Votes are one of the main criteria we use to determine which bugs to fix next.
This behavior has not changed. Cascade means refresh the related objects, the relationships of the source object must always be rebuilt from the row. If they are not refreshed then your lock will not prevent concurrent changes to these relationships.
Created attachment 226750 [details] test case Added test case: @Entity public class A { @OneToMany( mappedBy = "a") public Set<B> bs = new HashSet< B >(); ... @Entity public class B { @ManyToOne public A a; ... A a = new A(); em.getTransaction().begin(); em.persist( a ); em.getTransaction().commit(); em.getTransaction().begin(); em.lock( a, LockModeType.PESSIMISTIC_WRITE ); //causes in 2.1.1: // SELECT ID FROM A WHERE (ID = :1) FOR UPDATE //causes in 2.4: // SELECT ID FROM A WHERE (ID = :1) FOR UPDATE // SELECT ID, A_ID FROM B WHERE (A_ID = :1) ... The behaviour of 2.1.1 is ok for me, because I don't mind if the Bs are changed concurrently. In fact I know, that the Bs won't change concurrently. Interestingly there is a similar scenario where 2.4 behaves the same way as 2.1.1, which seems at least a bit inconsistent to me: A a = new A(); em.getTransaction().begin(); em.persist( a ); em.getTransaction().commit(); id = a.id; ...get new EntityManager... A a = em.find( A.class, id ); em.getTransaction().begin(); em.lock( a, LockModeType.PESSIMISTIC_WRITE ); //causes in 2.1.1, as well as in 2.4: // SELECT ID FROM A WHERE (ID = :1) FOR UPDATE ... .hg/patches contains a patch, to switch the test case from 2.1.1 to 2.4.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink