繁体   English   中英

JPA Criteria API检查关联集合是否为另一个集合的子集

[英]JPA Criteria API checking if an association collection is a subset of another collection

我有2张桌子: joblanguage 这两个表之间的关系为m:n,这意味着一个作业可能需要多种语言,而许多作业可能需要一种语言。 因此,我必须创建第三个表job_language来表示这种关系,它只包含两列job_id (是整数)和language_code (例如, 'eng'表示英语, 'jap'表示日语,等等)。 我正在使用的数据库是MySQL。

现在,我必须使用Spring Data JPA创建REST服务,以获取需要一组语言的所有作业,这些语言是用户输入中另一组语言的子集。 例如,假设我有3个作业,它们具有表job_language的值,如下所示:

--------------------------
| job_id | language_code |
--------------------------
| 1      | 'eng'         |
--------------------------
| 2      | 'eng'         |
--------------------------
| 2      | 'vie'         |
--------------------------
| 3      | 'jap'         |
--------------------------
| 3      | 'eng'         |
--------------------------
| 3      | 'vie'         |
--------------------------

现在,用户想要查找需要('eng', 'vie') (这是从用户输入创建的language_code的列表)的作业,查询应返回两个作业: job_id = 1 job和job_id = 2 job。

这些是我的实体类:

@Entity
public class Job {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ManyToMany
    @JoinTable(name = "job_language", 
        joinColumns = { @JoinColumn(name = "job_id", nullable = false) },
        inverseJoinColumns = { @JoinColumn(name = "language_code", nullable = false) })
    private List<Language> languages;

    // getters and setters here...
}

@Entity
public class Language { 
    @Id
    @Column(columnDefinition = "char", length = 3)
    private String code;

    @Column(length = 100)
    private String name;

    // getters and setters...
}

我有一个完全符合此要求的MySQL查询,但是由于JPQL不允许左连接两个不相关的表,因此无法使用JPA Criteria API找到解决方案。 有什么建议么?

这是我的工作查询:

select jl1.job_id
from job_language jl1 left join job_language jl2 on jl1.job_id = jl2.job_id and jl1.language_code = jl2.language_code and jl2.language_code in ('eng', 'vie')
group by jl1.job_id
having count(jl1.language_code) = count(jl2.language_code);

您可以将查询用作带有Spring Data存储库的本机SQL查询。 举个例子:

public interface JobRepository extends JobRepository<Job, Long> {
  @Query(nativeQuery = true
      , value = "SELECT "
              + "  * "
              + "FROM"
              + "  job "
              + "WHERE "
              + "  id IN "
              + "  ( "
              + "  SELECT "
              + "    jl1.job_id "
              + "  FROM "
              + "    job_language jl1 "
              + "  LEFT JOIN "
              + "    job_language jl2 "
              + "  ON "
              + "    jl1.job_id = jl2.job_id "
              + "  AND jl1.language_code = jl2.language_code "
              + "  AND jl2.language_code IN ?1 "
              + "  GROUP BY "
              + "    jl1.job_id "
              + "  HAVING "
              + "    COUNT(jl1.language_code) = COUNT(jl2.language_code) "
              + "  )")
  List<Job> findAllByLanguageCodes(String... languageCodes);
}

使用本机查询的唯一标准是Spring Data应该能够将本机查询的返回值转换为带注释方法的返回类型。 我们通过在查询的顶部放置一个SELECT * FROM job来利用这一点,这使Spring Data JPA可以很好地处理结果,因为该job已映射到JPA实体(即使不是真正驱动查询的job_location , )。

在这里查看工作示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM