I have a lazy 1:n relation from Bp
to BpHistorisiert
and I'm failing to tell JPA to load this realtion eagerly.
I have a criteria query that does a fetch join to load BpHistorisiert
together with Bp
.
Unfortunately it's not working, no BpHistorisiert
instances are loaded at all. The bpHistorisiertList
in Bp
reamins empty.
This is the JPQL Query that is generated by the criteria API:
SELECT * FROM Bp b LEFT JOIN FETCH b.bpHistorisiertList
And JPA is generating this SQL Query:
SELECT t0.id,
t6.bp_id,
t6.id,
FROM infop_stammdaten.bp t0
LEFT OUTER JOIN infop_stammdaten.bp_historisiert t6
ON t0.id = t6.bp_id
ORDER BY t6.bp_id ASC;
If I execute this query in the DB I do get the correct data.
Bp
@Entity
@Table(name = "BP", schema = "INFOP_STAMMDATEN")
public class Bp extends BaseEntity implements EntityId, Serializable {
/** technische ID */
@Id
@Column(name = ID)
private Long id;
@Valid
@OneToMany(mappedBy = "bp", orphanRemoval = false, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<BpHistorisiert> bpHistorisiertList = new ArrayList<>();
}
BpHistorisiert
@Entity
@Table(name = "BP_HISTORISIERT", schema = "INFOP_STAMMDATEN")
public class BpHistorisiert implements EntityId, GueltigkeitOwner, AbkuerzungOwner, Serializable {
@Id
@Column(name = ID)
private Long id;
@NotNull
@ManyToOne
@JoinColumn(name = BP_ID)
@ForeignKey
private Bp bp;
}
Query
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Bp> bpQuery = builder.createQuery(Bp.class);
Root<Bp> fromBp = bpQuery.from(Bp.class);
fromBp.fetch(Bp_.bpHistorisiertList, JoinType.LEFT);
List<Bp> bpList = entityManager.createQuery(bpQuery).getResultList();
After all this turned out to be a persistence context live cycle problem. The entity definition and the criteria query are perfectly fine.
Background
Our handcrafted test-JEE container does not clear the persistence context in this particular case. Further more the DB initialization code did not set both sides of the bidirectional relation between Bp and BpHistorisert. This caused the entity manager to work with the a broken Bp to BpHistorisert relation from the persistence context instead of reading everything from scratch from the DB.