【问题标题】:JPA - Specifications with custom left joinJPA - 具有自定义左连接的规范
【发布时间】:2020-10-03 20:18:24
【问题描述】:

我有 4 个实体:Parent, Alpha, Omega, Beta。

@Audited @Entity @Table(name = "parent")
public class Parent extends AuditEntity  {

    @Id @Column(nullable = false)
    @GeneratedValue ....
    private Long id;

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL,
            orphanRemoval = true)
    @JsonIgnore
    private Set<Alpha> alphas;
}

/**
*   Alpha connects Parent & Omega by containing their Ids mapping. It uses ParentAlphaId.java as ID class.
*/
@Audited @Entity @Table (name = "alpha")
@IdClass(ParentAlphaId.class)
public class Alpha extends AuditEntity {

    @Id
    @Column(name = "parent_id", nullable = false)
    private Long parentId;

    @Id
    @Column(name = "omega_id", nullable = false)
    private Long omegaId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
    private Parent parent;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "omega_id", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
    private Omega omega;

}

@Entity @Audited @Table(name = "omega"
public class Omega extends AuditEntity {

    @Id
    @GeneratedValue ....
    private long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "beta", nullable = false)
    private Beta beta;

}

@Entity @Audited @Table(name = "beta")
public class Beta extends AuditEntity {

    @Id @Column
    private long id;

    @Column(nullable = false)
    private Integer archived;   // archived can be 0 or 1.
}

我想运行以下查询:

SELECT
    p.id,
    a.id,
    o.id,
    b.id, b.archived
FROM
    parent p
    LEFT JOIN alpha   a ON a.parent_id = p.id
    LEFT JOIN omega   o ON a.omega_id = o.id
    LEFT JOIN beta    b ON o.beta_id = b.id AND d.archived = 0;

意图是从父级、alpha 和 omega 那里获取 id,在 beta 中归档为 0。

而对于其他beta为1的记录,将被报告为null。

为此,我在 Parent 的存储库中编写了以下规范,即 root 位于 Parent:

public static Specification<Parent> getParentWithActiveBeta() {
    return (root, query, cb) -> {
        Fetch<Object, Object> alpha = root.fetch("alpha", JoinType.LEFT);
        Fetch<Object, Object> omega = alpha.fetch("omega", JoinType.LEFT);
        Fetch<Object, Object> beta = omega.fetch("beta", JoinType.LEFT);
        beta.on(cb.equal(beta.get("archived"), 0));
        return null;
    };
}

SQL 查询似乎工作正常,但是当我运行规范时,我会得到那些归档为 1 的记录的 beta Id。

我原以为它们会为空。

我错过了什么?

【问题讨论】:

    标签: java oracle hibernate jpa


    【解决方案1】:

    您不应该使用fetch,而是使用join,因为fetch 会导致JPQL/HQL join fetch 不支持ON 谓词。您可以使用如下存储库方法:

    @Query("SELECT p.id, a.id, o.id, b.id, b.archived FROM Parent p JOIN p.alphas a JOIN a.omega o JOIN o.beta b ON b.archived = false")
    public List<Tuple> findWhatever();
    

    【讨论】:

      猜你喜欢
      • 2017-05-12
      • 2021-01-30
      • 1970-01-01
      • 1970-01-01
      • 2021-06-22
      • 1970-01-01
      • 1970-01-01
      • 2014-11-17
      • 2014-11-07
      相关资源
      最近更新 更多