I have the following Entities; The ticket contains set 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 load tickets and get attributes. All attributes of 0.1 are not a 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();
As a result, in the request, which should return 1 ticket to me with 5 workOrders, I get the same ticket 5 times.
If I just do workOrders Eager Fetch and delete the extraction code, it works as it should.
Can anyone help me? Thanks in advance.
UPDATE:
One explanation of why I'm not just happy with JB Nizet's answer (even if it works in the end).
When I just make relationships impatient, the JPA examines the exact same data as when I make it lazy and add a fetch clause to the / JPQL criterion. The relationships between the various elements are also clear as I am defining a ListAttribute for a Criteria request.
Is there any reasonable explanation for the reason that the JPA does not return the same data in both cases?
UPDATE FOR BOUNTY: although JB Nizet's answer resolved the problem, I still find it pointless that, given the two operations with the same value ("Get Ticket and fetching all WorkOrder inside ticket.workOrders "), perform them using the downloaded download does not require any additional changes, while the DISTINCT command is required to specify a selection