I have the following Entities; Ticket contains a set of 0,N WorkOrder:
@Entity
public class Ticket {
...
@OneToMany(mappedBy="ticket", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<WorkOrder> workOrders = null;
...
}
@Entity
public class WorkOrder {
...
@ManyToOne
@JoinColumn(nullable = false)
private Ticket ticket;
}
I am loading Tickets and fetching the attributes. All of the 0,1 attributes present no problem. For workOrders, I used this answer to get the following code.
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Ticket> criteriaQuery = criteriaBuilder
.createQuery(Ticket.class);
Root<Ticket> rootTicket = criteriaQuery.from(Ticket.class);
ListAttribute<? super Ticket, WorkOrder> workOrders =
rootTicket.getModel().getList("workOrders", WorkOrder.class);
rootTicket.fetch(workOrders, JoinType.LEFT);
// WHERE logic
...
criteriaQuery.select(rootTicket);
TypedQuery<Ticket> query = this.entityManager.createQuery(criteriaQuery);
return query.getResultList();
The result is that, in a query that should return me 1 Ticket with 5 workOrders, I am retrieving the same Ticket 5 times.
If I just make the workOrders an Eager Fetch and delete the fetch code, it works as it should.
Can anyone help me? Thanks in advance.
UPDATE:
One explanation about why I am not just happy with JB Nizet's answer (even if in the end it works).
When I just make the relationship eager, JPA is examining exactly the same data that when I make it lazy and add the fetch clause to the Criteria / JPQL. The relationships between the various elements is also clear, as I define the ListAttribute
for the Criteria query.
There is some reasonable explanaition for the reason that JPA does not return the same data in both cases?
UPDATE FOR BOUNTY: While JB Nizet's answer did solve the issue, I still find it meaningless that, given two operations with the same meaning ("Get Ticket
and fetch all WorkOrder
inside ticket.workOrders
"), doing them by an eager loading needs no further changes while specifying a fetch requires a DISTINCT
command
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…