【问题标题】:JPA JOIN FETCH query is not loading dataJPA JOIN FETCH 查询未加载数据
【发布时间】:2018-06-19 10:31:46
【问题描述】:

我有一个从 BpBpHistorisiert 的惰性 1:n 关系,并且我没有告诉 JPA 急切地加载这个 realtion。

我有一个条件查询,它执行 fetch join 以加载 BpHistorisiertBp

不幸的是,它不起作用,根本没有加载任何 BpHistorisiert 实例。 Bp 中的 bpHistorisiertList 仍为空。

这是标准 API 生成的 JPQL 查询:

SELECT * FROM Bp b LEFT JOIN FETCH b.bpHistorisiertList

JPA 正在生成这个 SQL 查询:

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; 

如果我在数据库中执行此查询,我会得到正确的数据。

血压

@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;

}

查询

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

【问题讨论】:

  • 我不明白会发生什么。你说当你手动执行生成的语句时,你确实得到了数据,但是集合是空的。这是正确的,还是会发生什么?
  • 是的。我确实得到了Bps 的列表,但所有bpHistorisiertLists 仍然是空的。
  • 空不等于未初始化。你的意思是当你访问列表时它是空的还是你的意思是当你访问列表时它是延迟加载的?如果它确实是空的,也许您应该启用跟踪日志记录 (ci.apache.org/projects/openjpa/trunk/docbook/…)?
  • 这是一个 ArrayList 代理。当我访问它时,什么都没有加载,它的大小是 0。

标签: java jpa criteria-api openjpa


【解决方案1】:

毕竟这是一个持久性上下文生命周期问题。实体定义和条件查询都很好。

背景

在这种特殊情况下,我们手工制作的 test-JEE 容器不会清除持久性上下文。此外,DB 初始化代码没有设置 Bp 和 BpHistorisert 之间双向关系的两侧。这导致实体管理器从持久性上下文中处理损坏的 Bp 到 BpHistorisert 关系,而不是从头开始从数据库中读取所有内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-11
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 2011-05-19
    相关资源
    最近更新 更多