I can illustrate the problem I'm seeing with a simple entity called Person which has a self-join to its parent:
@Entity
@Table(name = "Person")
public class Person {
private Long id;
private Person parent;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "parentId", insertable = false, updatable = false)
public Person getParent() {
return parent;
}
public void setParent(Person parent) {
this.parent = parent;
}
}
I've written a query using the JPA Criteria API to return a Person with their parent, locking both the child and parent rows:
private Person selectForUpdate(EntityManager em, Long id) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> personRoot = criteria.from(Person.class);
ParameterExpression<Long> personIdParameter = builder.parameter(Long.class);
personRoot.fetch("parent", JoinType.LEFT);
criteria
.select(personRoot)
.where(builder.equal(personRoot.get("id"), personIdParameter));
List<Person> persons = em.createQuery(criteria)
.setParameter(personIdParameter, id)
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.getResultList();
return persons.isEmpty() ? null : persons.get(0);
}
Using either Hibernate 5.2.2-FINAL or Hibernate 4.3.11-FINAL running on JDK 8, the generated SQL query is corrupted:
select
person0_.id as id1_0_0_,
person1_.id as id1_0_1_,
person0_.parentId as parentId2_0_0_,
person1_.parentId as parentId2_0_1_
from
Person person0_
left outer joinperson0_ with (updlock,
rowlock)person1_ with (updlock,
rowlock)
on person0_.parentId=person1_.id where
person0_.id=?
I get the same result using JPQL. This query worked as expected with Hibernate 4.3.11-FINAL running on JDK 7, generating the query:
select
person0_.id as id1_0_0_,
person1_.id as id1_0_1_,
person0_.parentId as parentId2_0_0_,
person1_.parentId as parentId2_0_1_
from
Person person0_ with (updlock, rowlock)
left outer join
Person person1_ with (updlock, rowlock)
on person0_.parentId=person1_.id
where
person0_.id=?
I've attached a sample TestCase which highlights the problem. |