I'm in the process of converting Hibernate Criteria queries to JPA Criteria ones (in an application that will be using Hibernate 5.2.12) and have encountered some issues with joins and aliasing. I can't tell where I'm going wrong and am hoping that someone else can shed some light on the subject for me.
If I take an entity (Entity 1 with alias A) and join it to a second entity (Entity 2 with alias B), the code will only "see" the fields associated with B, not the A, using the join. Aliasing doesn't seem to work the way that I am used to in the Hibernate API, i.e., I can't reference fields by A.field1, A.field2, B.field3, B.field4 when selecting query items or using those fields to constrain the query.
I've examples below of what works and what does not using two skeleton classes, Person and Phone.
Code:
@Entity
public class Person {
@Id
private Integer id;
@Column
private String name;
@ManyToOne
private Phone Phone;
}
@Entity
public class Person {
@Id
private Integer id;
@Column
private String number;
@OneToMany
private List<Persons> persons;
}
JPA Criteria examples: Selecting a list of Person entities (persons) succeeds:
Code:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery( Person.class );
Root<Person> personRoot = criteria.from( Person.class );
personRoot.alias("a");
Join<Person,Phone> join = personRoot.join( "phone" );
personRoot.alias("b");
criteria.select( personRoot );
TypedQuery<Person> tq = entityManager.createQuery(criteria);
List<Person> persons = tq.getResultList();
Attempting to restrict the list by a person's name using the join fails:
<==== What I would like to doCode:
criteria.select( personRoot );
criteria.where( builder.equal( join.get( "name" ), "John Doe" ) );
TypedQuery<Person> tq = entityManager.createQuery(criteria);
List<Person> persons = tq.getResultList();
Attempting to restrict the list by a phone number on the join succeeds:
<==== What I would like to doCode:
criteria.select( personRoot );
criteria.where( builder.equal( join.get( "number" ), "999999999" ) );
TypedQuery<Person> tq = entityManager.createQuery(criteria);
List<Person> persons = tq.getResultList();
Attempting to restrict the list by a person's name using getParent() on the join succeeds:
<==== What works but I don't want to doCode:
criteria.select( personRoot );
criteria.where( builder.equal( join.getParent().get( "name" ), "John Doe" ) );
TypedQuery<Person> tq = entityManager.createQuery(criteria);
List<Person> persons = tq.getResultList();
Attempting to accessing a field using an alias fails:
<==== What I would like to doCode:
criteria.select( personRoot );
criteria.where( builder.equal( join.get( "a.name" ), "John Doe" ) );
TypedQuery<Person> tq = entityManager.createQuery(criteria);
List<Person> persons = tq.getResultList();