我有2个表:job
和language
。这两个表之间的关系是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_id = 2
。
这些是我的实体类:
@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);
答案 0 :(得分:0)
您可以将查询用作具有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
,这真的驱动查询,不是)。
查看工作示例here。