我有以下场景
@Entity
public class Parent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name = "name", nullable = false)
private String name;
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
private Set<Child> children;
}
@Entity
public class Child {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch=FetchType.LAZY, optional = false)
private Parent parent;
}
当使用JPACcriteria或JPQL构建查询时,在为子级请求联接获取时,默认情况下我会获得内部联接。
使用:
SELECT p from Parent p JOIN p.children
或
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Parent> query = cb.createQuery(Parent.class);
Root<Parent> root = query.from(Parent.class);
root.fetch(Parent_.children);
query.distinct(true);
List<Parent> result = em.createQuery(query).getResultList();
如何避免这种默认行为(内部联接)?我的目标是在指定OneToMany关系时默认获得LEFT JOIN。。。在构建查询时,是否可以不显式设置JoinType.LEFT
非常感谢您的帮助。提前感谢
在构建查询时,是否可以不显式设置JoinType.LEFT?
不,不是!隐式联接是INNER join,如果您在JPQL查询中导航关联,就会假定它。
如果还需要获取子关联,则必须使用LEFT JOIN和FETCH:
SELECT p
from Parent p
LEFT JOIN FETCH p.children
或符合API标准:
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Parent> query = cb.createQuery(Parent.class);
Root<Parent> root = query.from(Parent.class);
root.fetch(Parent_.children, JoinType.LEFT);
query.distinct(true);
List<Parent> result = em.createQuery(query).getResultList();
您可以尝试Blaze Persistence,因为它以您期望的方式进行隐式联接,即只有在保留行数的情况下才进行内部联接。
List<Parent> result = cbf.create(em, Parent.class).fetch("children").getResultList();
生成
SELECT p
FROM Parent p
LEFT JOIN FETCH p.children