JPA JOIN FETCH 查询未加载数据
JPA JOIN FETCH query is not loading data
我有一个从 Bp
到 BpHistorisiert
的惰性 1:n 关系,我没有告诉 JPA 急切地加载这个 realtion。
我有一个条件查询,它执行提取连接以加载 BpHistorisiert
和 Bp
。
不幸的是它没有工作,根本没有加载 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;
如果我在数据库中执行此查询,我会得到正确的数据。
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;
}
查询
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();
毕竟这是一个持久性上下文生命周期问题。实体定义和条件查询完全没问题。
背景
在这种特殊情况下,我们手工制作的测试 JEE 容器不会清除持久性上下文。此外,DB 初始化代码没有设置 Bp 和 BpHistorisert 之间双向关系的两侧。这导致实体管理器从持久性上下文中使用损坏的 Bp 到 BpHistorisert 关系,而不是从数据库中从头开始读取所有内容。
我有一个从 Bp
到 BpHistorisiert
的惰性 1:n 关系,我没有告诉 JPA 急切地加载这个 realtion。
我有一个条件查询,它执行提取连接以加载 BpHistorisiert
和 Bp
。
不幸的是它没有工作,根本没有加载 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;
如果我在数据库中执行此查询,我会得到正确的数据。
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;
}
查询
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();
毕竟这是一个持久性上下文生命周期问题。实体定义和条件查询完全没问题。
背景
在这种特殊情况下,我们手工制作的测试 JEE 容器不会清除持久性上下文。此外,DB 初始化代码没有设置 Bp 和 BpHistorisert 之间双向关系的两侧。这导致实体管理器从持久性上下文中使用损坏的 Bp 到 BpHistorisert 关系,而不是从数据库中从头开始读取所有内容。