JPQL 多对多带 in 子句
JPQL Many to Many with in Clause
我想知道是否有办法将我的本机查询转换为 JPQL 查询。
查询
public interface GraphJobRepository extends JpaRepository<GraphJob, Long> {
@Query(value = "Select * From graph_job where id in (\n" +
" SELECT distinct g.graph_job_id\n" +
" FROM graph_job_role g\n" +
" INNER JOIN clover_role r ON g.clover_role_id = r.role_id\n" +
" WHERE r.role_name in (:roles))",
nativeQuery = true)
List<GraphJob> findGraphJobsByRoles(@Param("roles") List<String> roles);
}
三叶草角色
@Data
@Entity
public class CloverRole {
@Id
@Column(name = "role_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String roleName;
}
图形作业
@Entity
public class GraphJob {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@JoinTable(name = "graph_job_role", joinColumns = {
@JoinColumn(name = "graph_job_id")}, inverseJoinColumns = {
@JoinColumn(name = "clover_role_id")})
@ManyToMany
private Collection<CloverRole> roles;
}
我尝试过的任何方法都没有奏效,我确定如果我要添加 join table 实体我可以让它工作,但我想知道是否有人知道如何在没有实际上创建那个实体。
您可以尝试使用 member of
运算符、交叉连接和 List<String>
作为参数
@Query("select distinct j from GraphJob j, CloverRole r where r member of j.roles and r.roleName in(:roleNames)")
List<GraphJob> findGraphJobsByRoleNames(@Param("roleNames") List<String> roleNames);
如果您的目标是摆脱嵌入的字符串,您可以使用 FluentJPA 作为纯粹的 Java 解决方案:
(无需更改现有代码)
public interface GraphJobRepository extends JpaRepository<GraphJob, Long>,
EntityManagerSupplier {
default List<GraphJob> findGraphJobsByRoles(List<String> roles) {
FluentQuery query = FluentJPA.SQL((GraphJob job) -> {
List<Long> jobIds = subQuery((CloverRole r,
JoinTable<GraphJob, CloverRole> graphJobRole) -> {
SELECT(graphJobRole.getJoined().getId());
FROM(graphJobRole).JOIN(r)
.ON(graphJobRole.inverseJoin(r, GraphJob::getRoles));
WHERE(roles.contains(r.getRoleName()));
});
SELECT(job);
FROM(job);
WHERE(jobIds.contains(job.getId()));
});
return query.createQuery(getEntityManager(), GraphJob.class).getResultList();
}
}
产生以下 SQL:
SELECT t0.*
FROM graph_job t0
WHERE (t0.id IN (SELECT t2.graph_job_id
FROM graph_job_role t2 INNER JOIN clover_role t1 ON (t2.clover_role_id = t1.role_id)
WHERE (t1.role_name IN ?1 )) )
FluentJPA先提供classJPA Repository integration and supplies a "virtual" join table.
我想知道是否有办法将我的本机查询转换为 JPQL 查询。
查询
public interface GraphJobRepository extends JpaRepository<GraphJob, Long> {
@Query(value = "Select * From graph_job where id in (\n" +
" SELECT distinct g.graph_job_id\n" +
" FROM graph_job_role g\n" +
" INNER JOIN clover_role r ON g.clover_role_id = r.role_id\n" +
" WHERE r.role_name in (:roles))",
nativeQuery = true)
List<GraphJob> findGraphJobsByRoles(@Param("roles") List<String> roles);
}
三叶草角色
@Data
@Entity
public class CloverRole {
@Id
@Column(name = "role_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String roleName;
}
图形作业
@Entity
public class GraphJob {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@JoinTable(name = "graph_job_role", joinColumns = {
@JoinColumn(name = "graph_job_id")}, inverseJoinColumns = {
@JoinColumn(name = "clover_role_id")})
@ManyToMany
private Collection<CloverRole> roles;
}
我尝试过的任何方法都没有奏效,我确定如果我要添加 join table 实体我可以让它工作,但我想知道是否有人知道如何在没有实际上创建那个实体。
您可以尝试使用 member of
运算符、交叉连接和 List<String>
作为参数
@Query("select distinct j from GraphJob j, CloverRole r where r member of j.roles and r.roleName in(:roleNames)")
List<GraphJob> findGraphJobsByRoleNames(@Param("roleNames") List<String> roleNames);
如果您的目标是摆脱嵌入的字符串,您可以使用 FluentJPA 作为纯粹的 Java 解决方案:
(无需更改现有代码)
public interface GraphJobRepository extends JpaRepository<GraphJob, Long>,
EntityManagerSupplier {
default List<GraphJob> findGraphJobsByRoles(List<String> roles) {
FluentQuery query = FluentJPA.SQL((GraphJob job) -> {
List<Long> jobIds = subQuery((CloverRole r,
JoinTable<GraphJob, CloverRole> graphJobRole) -> {
SELECT(graphJobRole.getJoined().getId());
FROM(graphJobRole).JOIN(r)
.ON(graphJobRole.inverseJoin(r, GraphJob::getRoles));
WHERE(roles.contains(r.getRoleName()));
});
SELECT(job);
FROM(job);
WHERE(jobIds.contains(job.getId()));
});
return query.createQuery(getEntityManager(), GraphJob.class).getResultList();
}
}
产生以下 SQL:
SELECT t0.*
FROM graph_job t0
WHERE (t0.id IN (SELECT t2.graph_job_id
FROM graph_job_role t2 INNER JOIN clover_role t1 ON (t2.clover_role_id = t1.role_id)
WHERE (t1.role_name IN ?1 )) )
FluentJPA先提供classJPA Repository integration and supplies a "virtual" join table.