Right now, In a short example, if i have two entities Person and Applicant and i want to write a query that gets all applicants in my database, i end up getting referenced queries with the following set up. I am using Single_Table_Inheritance strategy (fyi)
public class Person {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "schoolID")
private School school;
}
The Teacher object with a reference to another entity.
public class Applicant extends Person {
@OneToMany(targetEntity = ApplicantSchool.class, cascade = { javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REMOVE }, mappedBy = "applicant")
private Set<ApplicantSchool> schools = new HashSet<ApplicantSchool>();
}
Query attempt that jumps and attempts to query for the school relationship in Person
public List<Applicant> getAllApplicants(){
EntityManager entityManager = factory.createEntityManager();
@SuppressWarnings("unchecked")
List<Applicant> applicants = entityManager.createQuery("Select a from Applicant a LEFT JOIN FETCH a.schools WHERE a.active = :active ")
.setParameter("active", true).setHint("eclipselink.refresh", "true")
.getResultList();
//List<Applicant> applicants = Applicant.findAllApplicants();
System.out.println("The long query getting applicants");
entityManager.close();
return applicants;
}
If i try to change my query to use nested joining, i get an error saying relationship not recognized. I tried to query like so:
entityManager.createQuery("Select a from Applicant a LEFT JOIN FETCH a.schools WHERE LEFT JOIN FETCH a.person.school a.active = :active ")
UPDATED
After removing the keyword “left join fetch” my new query:
List<Applicant> applicants = entityManager.createQuery("Select a from Applicant a WHERE a.active = :active ")
.setParameter("active", true)
.getResultList();
The only query i agree with that it first creates is this one
SELECT personID, TYPE, DATEADDED, FIRSTNAME, LASTNAME, MIDDLENAME, ACTIVE, BIRTHDAY, EMAILADDRESS, ETHNICITY, GENDER, HISPANIC, IMAGEPATH, MARITAL, NATIVELANGUAGE, PRIMARYTELEPHONE, RELIGIOUSAFFILIATION, SECONDARYTELEPHONE, version, addressID, schoolID, MAJOR FROM PERSON WHERE ((ACTIVE = ?) AND (TYPE = ?))
bind => [true, AP]
Returns this stack trace and the following sql’s selects are created:
[EL Fine]: sql: 2012-07-13 17:25:52.297--ServerSession(1529073996)--Connection(726700617)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT schoolID, ACTIVE, ADMISSIONSEMAILADDRESS, ADMISSIONSPHONE, CODE, description, HELPGENERALEMAILADDRESS, NAME, PRIMARYPHONE, version, addressID FROM SCHOOL WHERE (schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.305--ServerSession(1529073996)--Connection(1615948530)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT id, ACTIVE, CODE, DESCRIPTION, NAME, version, SCHOOLDEPARTMENT_schoolID FROM DEPARTMENT WHERE (SCHOOLDEPARTMENT_schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.308--ServerSession(1529073996)--Connection(893810654)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT programID, ACTIVE, CODE, description, NAME, PROGRAMTYPE, REQUIREDCREDITS, version, SCHOOL_schoolID FROM PROGRAM WHERE (SCHOOL_schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.31--ServerSession(1529073996)--Connection(399107363)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT personID, TYPE, DATEADDED, FIRSTNAME, LASTNAME, MIDDLENAME, ACTIVE, BIRTHDAY, EMAILADDRESS, ETHNICITY, GENDER, HISPANIC, IMAGEPATH, MARITAL, NATIVELANGUAGE, PRIMARYTELEPHONE, RELIGIOUSAFFILIATION, SECONDARYTELEPHONE, version, addressID, schoolID, MAJOR, studentId FROM PERSON WHERE (schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.314--ServerSession(1529073996)--Connection(464642021)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT registrationId, SEMESTERTYPE, version, YEAR, semesterCourseId, personID FROM REGISTRATION WHERE (personID = ?)
bind => [501]
[EL Fine]: sql: 2012-07-13 17:25:52.322--ServerSession(1529073996)--Connection(395757277)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT registrationId, SEMESTERTYPE, version, YEAR, semesterCourseId, personID FROM REGISTRATION WHERE (personID = ?)
bind => [552]
[EL Fine]: sql: 2012-07-13 17:25:52.327--ServerSession(1529073996)--Connection(328677993)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT registrationId, SEMESTERTYPE, version, YEAR, semesterCourseId, personID FROM REGISTRATION WHERE (personID = ?)
bind => [602]
[EL Fine]: sql: 2012-07-13 17:25:52.358--ServerSession(1529073996)--Connection(873312397)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT addressID, CITY, COUNTRY, STATE_US, STREETADDRESS, STREETADDRESS2, version, ZIPCODE FROM ADDRESS WHERE (addressID = ?)
bind => [2]
[EL Fine]: sql: 2012-07-13 17:25:52.365--ServerSession(1529073996)--Connection(509650638)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT applicantSchoolID, CREDITSCOMPLETED, FROMMONTH, FROMYEAR, GPA, NAME, SCHOOLTYPE, TOMONTH, TOYEAR, version, APPLICANT_personID FROM APPLICANTSCHOOL WHERE (APPLICANT_personID = ?)
bind => [151]
[EL Fine]: sql: 2012-07-13 17:25:52.385--ServerSession(1529073996)--Connection(17334753)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT applicantSchoolID, CREDITSCOMPLETED, FROMMONTH, FROMYEAR, GPA, NAME, SCHOOLTYPE, TOMONTH, TOYEAR, version, APPLICANT_personID FROM APPLICANTSCHOOL WHERE (APPLICANT_personID = ?)
bind => [51]
You cannot nest join in JPA, but you shouldn’t need to when querying on Applicant.
JPQL “Select a from Applicant a LEFT JOIN FETCH a.schools LEFT JOIN FETCH a.school where a.active = :active ” should work, since Appliant IS a Person and so has the school relationship. Nesting is only if Applicant has a relation to person and you needed to fetch join both person and school.
If that is the case, EclipseLink allows batch reading or joins through query hints described here:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/QueryOptimization
You can also specify batching/fetch joins at the mapping level using EclipseLink annotations described here:
http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_batchfetch.htm#CHDCCIDA
and
http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_joinfetch.htm#CEGFFHHA
Batch reading will result in 2 queries, while fetch joins in 1.
For the query described above, you could also use: