Reputation: 14741
I have the below mentioned Entity relationship. When I run my application, I can see that the below query generated by Hibernate executes 13 times(1+12) where 12 is the number of rows I am displaying in front end application. Ideally it should have executed only once as I am not sure why it is getting executed 12 times. If I change my number of rows to be displayed in front end application to say 20, then query executes 21 times.
How can I resolve this issue?
Hibernate auto generated query
select employee0_.EMPLOYEE_NUMBER as EMP1_2_0_, employee0_.DEPARTMENT_CODE as
DEPARTMENT3_2_0_, employee0_.EMPLOYEE_DEPT as EMPLOYEE4_2_0_, employee0_.DESIGNATION
as DESIGNAT5_2_0_, employee0_.EMPLOYEE_NAME as EMPLOYEE6_2_0_ from EMPLOYEES
employee0_ where employee0_.EMPLOYEE_NUMBER=?
Entity Classes
@Entity
public class Project
@ManyToOne
@JoinColumn(name = "EMPLOYEE_NUMBER", referencedColumnName = "EMPLOYEE_NUMBER")
private Employee requester;
@ManyToOne
@JoinColumn(name = "APPROVER", referencedColumnName = "EMPLOYEE_NUMBER")
private Employee approver;
}
@Entity
public class Employee {
@OneToMany(mappedBy = "requester")
private Set<Project> requestedProjects;
@OneToMany(mappedBy = "approver")
private Set<Project> approvedProjects;
}
JSF UI Source
<p:dataTable id="dataTable" var="proj" lazy="true"
value="#{projMB.lazyModel}" styleClass="projTableStyle"
paginator="true" paginatorPosition="bottom" rows="12"
rowKey="#{proj.projectId}">
<f:facet name="header">
<p:column id="employeeNo" headerText="Employee Name" width="16">
<h:outputText value="#{proj.empNumber.employeeName}" />
</p:column>
.....
.....
DAOImpl class where for retrieving records
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Project> c = cb.createQuery(Project.class);
Root<Project> emp = c.from(Project.class);
c.orderBy(cb.desc(emp.get("projectId")));
c.select(emp);
CriteriaQuery<Long> countQ = cb.createQuery(Long.class);
Root<Project> empCount = countQ.from(Project.class);
countQ.select(cb.count(empCount));
List<Predicate> criteria = new ArrayList<Predicate>();
if (projectId != null) {
ParameterExpression<String> pexp = cb.parameter(String.class,
"projectId");
Predicate predicate = cb.equal(emp.get(Project_.projectId), pexp);
criteria.add(predicate);
}
TypedQuery<Project> q = entityManager.createQuery(c);
Controller class
private List<Project> project = new ArrayList<Project>();
project = myservice.getDAOValues();
....
The table displays the following
Employee No, Employee Name, Project Id, Project Start Date
Edit 2
@ManyToOne
@JoinColumn(name = "REQUESTOR", referencedColumnName = "EMPLOYEE_NUMBER",
insertable = false, updatable = false)
private RequesterDepartment requesterDepartment;
Upvotes: 2
Views: 1437
Reputation: 692221
You want to load projects, and their respective requester or approver in a single query. This is done using a fetch join. In JPQL:
select p from Project p
left join fetch p.requester
where ...
And in Criteria, there is an equivalent construct:
Root<Project> project = c.from(Project.class);
project.fetch(Project_.requester, JoinType.LEFT);
Note that I renamed emp
to project
: emp
would be an almost acceptable name for an Employee path. Using it for a Project
path is extremely confusing.
Upvotes: 1