Java JPA-具有自定义左连接的规范

Java JPA-具有自定义左连接的规范,java,oracle,hibernate,jpa,Java,Oracle,Hibernate,Jpa,我有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

我有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.
}
其目的是从父级、alpha和omega获取ID,在beta中存档的ID为0

对于beta为1的其他记录,它将报告为null

为此,我在父级存储库中编写了以下规范,即
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;
    };
}
公共静态规范getParentWithActiveBeta(){
返回(根、查询、cb)->{
Fetch alpha=root.Fetch(“alpha”,JoinType.LEFT);
Fetch omega=alpha.Fetch(“omega”,JoinType.LEFT);
Fetch beta=omega.Fetch(“beta”,JoinType.LEFT);
beta.on(cb.equal(beta.get(“存档”),0));
返回null;
};
}
SQL查询似乎工作得很好,但当我运行规范时,我会得到归档为1的记录的测试版ID

我原以为它们会变成空的


我缺少什么?

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

@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();
@Query(“选择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”)
公共列表findWhatever();

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

@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();
@Query(“选择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”)
公共列表findWhatever();