Search code examples
javajpacriteria-apiopenjpa

JPA JOIN FETCH query is not loading data


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();

Solution

  • 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.