【问题标题】:Is it possible to define LEFT Join when annotating a relationship with @OneToMany?在使用@OneToMany 注释关系时是否可以定义 LEFT Join?
【发布时间】:2015-04-14 14:11:26
【问题描述】:

我有以下场景

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

使用 JPA Criteria 或 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?

非常感谢任何帮助。 提前谢谢你

【问题讨论】:

    标签: java hibernate jpa one-to-many criteria-api


    【解决方案1】:

    是否可以在构建查询时不显式设置 JoinType.LEFT?

    不,不是!隐式连接是在 JPQL 查询中导航关联时假定的 INNER JOIN。

    如果您还需要获取子关联,则必须使用 LEFT JOIN 和 FETCH:

    SELECT p 
    from Parent p 
    LEFT JOIN FETCH p.children
    

    或使用 Criteria 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();
    

    【讨论】:

    • 嗨弗拉德...我什至在问题中添加了这个...“在构建查询时是否可以不明确设置 JoinType.LEFT?”。我正在尝试找到可以使用注释来完成的事情。谢谢您的回答
    • 如果您将它们设置为惰性,则可以使用辅助选择。否则 ln EAGER fetch 将在内部加入它。
    • 我只是想知道是否有可能根据一些注解或注解的参数获得一个默认的 JoinType.... 例如:root.fetch(Parent_.children); 在我在问题中添加的这个 sn-p 中......它是否总是被定义为 JoinType.INNER?难道不能改变这个默认行为吗?
    • 不,这是不可能的。当您获取默认情况下的内连接或明确指定左外连接时。
    • 好的!非常感谢弗拉德!
    【解决方案2】:

    您可以尝试Blaze-Persistence,因为它会按照您期望的方式进行隐式连接,即仅在保留行数的情况下进行内部连接。

    List<Parent> result = cbf.create(em, Parent.class).fetch("children").getResultList();
    

    生成

    SELECT p 
    FROM Parent p 
    LEFT JOIN FETCH p.children
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      • 2019-02-08
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 2011-12-14
      • 2018-09-21
      相关资源
      最近更新 更多