如何通过两个字段加入(CriteriaBuilder)

Posted

技术标签:

【中文标题】如何通过两个字段加入(CriteriaBuilder)【英文标题】:How to join by two fields (CriteriaBuilder) 【发布时间】:2014-07-24 05:59:36 【问题描述】:

我有一个实体

@Entity
@Table(name = "`petition`")
@Getter
@Setter
public class Petition extends Auditable 

    private static final long serialVersionUID = -3234225397035713824L;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "petition_selected_school", joinColumns = 
            @JoinColumn(name = "petition_id", nullable = false, updatable = false),
            inverseJoinColumns = @JoinColumn(name = "school_id",
                    nullable = false, updatable = false))
    private List<School> selectedSchools;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "petition_basic_school", joinColumns = 
            @JoinColumn(name = "petition_id", nullable = false, updatable = false),
            inverseJoinColumns = @JoinColumn(name = "school_id",
                    nullable = false, updatable = false))
    private List<School> fullBasicSchoolList;


我想通过标准构建器构建这样的 SQL 选择

SELECT DISTINCT
  p.id
FROM petition p JOIN petition_selected_school s ON p.id = s.petition_id
  LEFT JOIN petition_basic_school b ON p.id = b.petition_id AND s.school_id = b.school_id
WHERE b IS NULL
ORDER BY p."id" ASC

我试过这个:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Petition> criteriaQuery = builder.createQuery(Petition.class);
Root root = criteriaQuery.from(Petition.class);
criteriaQuery.distinct(true);
Join join = root.join("selectedSchools");
Join join2 = root.join("fullBasicSchoolList", JoinType.LEFT,);
Predicate p = builder.equal(join2.get("school"),join.get("school"));
finalPredicateList.add(p);
criteriaQuery = criteriaQuery.where(builder.and(finalPredicateList.toArray(new Predicate[finalPredicateList.size()])));

但是生成的sql是这样的:

SELECT DISTINCT 
  petition0_.id AS col_0_0_
FROM "petition" petition0_ INNER JOIN petition_selected_school selectedsc1_ ON petition0_.id = selectedsc1_.petition_id
  INNER JOIN "school" school2_ ON selectedsc1_.school_id = school2_.id
  LEFT OUTER JOIN petition_basic_school fullbasics3_ ON petition0_.id = fullbasics3_.petition_id
  LEFT OUTER JOIN "school" school4_ ON fullbasics3_.school_id = school4_.id
WHERE petition0_.id = 245 AND school4_.school = school2_.school

主要问题是“如何不仅通过一个参数加入”?

p.id = b.petition_id AND s.school_id = b.school_id

【问题讨论】:

【参考方案1】:

您使用的是什么版本的 JPA?

在 JPA 2.1 中,您可以通过两个字段连接,只要其中一个字段通过以下方式确定关系:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Petition> criteriaQuery = builder.createQuery(Petition.class);
Root root = criteriaQuery.from(Petition.class);
criteriaQuery.distinct(true);
Join join = root.join("selectedSchools");
//FIRST CONDITION (BY ID)
Join join2 = root.join("fullBasicSchoolList", JoinType.LEFT,);
//NEW
join2.on([SECOND_CONDITION])
[...]

【讨论】:

以上是关于如何通过两个字段加入(CriteriaBuilder)的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有节点引用字段的情况下加入两个 Drupal CCK 内容类型?

如何通过 Map 的特定键合并/加入两个 Map 列表?

如何通过一个键加入两个 RDD? [复制]

C ++在关键字段上加入两个管道划分的文件

MySQL如何在两个字段上连接表

MongoDB:如何将仅出现在 $project 中的字段相乘?