Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 基于主查询JPA条件API创建子查询_Java_Jpa_Subquery_Criteria Api - Fatal编程技术网

Java 基于主查询JPA条件API创建子查询

Java 基于主查询JPA条件API创建子查询,java,jpa,subquery,criteria-api,Java,Jpa,Subquery,Criteria Api,我需要在JPA中编写一个类似的查询: SELECT a.id, b.status FROM atable a JOIN btable b ON a.btable_id = b.id where ( ( b.status = 'INITIAL' and a.main_atable_id is null ) or exists ( SELECT 1 FROM atable a2

我需要在JPA中编写一个类似的查询:

SELECT
  a.id,
  b.status
FROM
  atable a
  JOIN btable b ON a.btable_id = b.id
where
  (
    (
      b.status = 'INITIAL'
      and a.main_atable_id is null
    )
    or exists (
      SELECT
        1
      FROM
        atable a2
        JOIN btable b2 ON a2.btable_id = b2.id
      WHERE
        b2.status = 'INITIAL'
        and b2.main_atable_id = a.id
    )
  );

如您所见,
atable
有一个名为
main\u atable\u id
的列,该列创建了父子关系,其思想是存在一个主版本,其子版本是重复的

我需要构建一个子查询,该子查询几乎与父查询相同。我会手工编写它,只是复制代码,但我希望尽可能地通过重用主查询的
规范来保持它的简单

现在,我的主要查询如下所示:

public Page<AtableDTO> findAtables(AtableSearchDTO filter, Pageable pageable) {
    Specifications<Atable> where = Specifications.where(alwaysTrue());

    if(filter.getStatus() != null) {
        where = where.and(statusEquals(filter.getStatus()));
    }

    Page<AtableDTO> resultPage = atableRepository.findAll(where, new PageRequest(pageable.getPageNumber(), pageable.getPageSize(), Sort.Direction.DESC, "id")).map(atableMapper::toDto);
}

public Specification<Atable> alwaysTrue() {
    return (root, query, cb) -> cb.and();
}

public Specification<Atable> statusEquals(AtableStatus value) {
    return (root, query, cb) -> cb.equal(root.get("status"), value);
}
publicpagefindatables(AtableSearchDTO-filter,Pageable-Pageable){
规格,其中=规格。其中(alwaysTrue());
if(filter.getStatus()!=null){
其中=where.and(statusEquals(filter.getStatus());
}
Page resultPage=atableRepository.findAll(其中,新页面请求(pageable.getPageNumber(),pageable.getPageSize(),Sort.Direction.DESC,“id”)).map(atableMapper::toDto);
}
公共规范alwaysTrue(){
return(root,query,cb)->cb.and();
}
公共规范statusEquals(AtableStatus值){
return(root,query,cb)->cb.equal(root.get(“status”),value);
}
我只想知道:

1) 是否可以重复使用相同的
规范

2) 如果是,你能在这个或任何其他简单的例子上演示吗


谢谢

为什么存在
子句
?您的查询相当于:

SELECT
  a.id,
  b.status
FROM
  atable a
  JOIN btable b ON a.btable_id = b.id
  JOIN btable b2 ON a.btable_id = b2.id
WHERE (b.status = 'INITIAL' AND a.main_atable_id IS NULL)
OR (b2.status = 'INITIAL' AND b2.main_atable_id = a.id);
(见附件)

假设您的实体具有以下结构:

@Entity
public class ATable {

    @Id
    private Long id;

    @OneToOne
    @JoinColumn(name = "btable_id")
    private BTable b;

    @ManyToOne
    @JoinColumn(name = "atable_main_id")
    private ATable main;
}

@Entity
public class BTable {

    @Id
    private Long id;

    private Status status;

    @ManyToOne
    @JoinColumn(name = "atable_main_id")
    private ATable main;
}
您需要以下查询:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> criteria = cb.createQuery(Object[].class);
Root<ATable> a = criteria.from(ATable.class);
Join<ATable, BTable> b = a.join("b");
Join<ATable, BTable> b2 = a.join("b");

criteria.where(cb.or(
        cb.and(
                cb.equal(b.get("status"), cb.literal(Status.INITIAL)),
                a.get("main").isNull()),
        cb.and(
                cb.equal(b2.get("status"), cb.literal(Status.INITIAL)),
                cb.equal(b2.get("main"), a)
                )));

criteria.multiselect(a.get("id"), b.get("status"));
CriteriaBuilder cb=em.getCriteriaBuilder();
CriteriaQuery criteria=cb.createQuery(Object[].class);
根a=标准.from(ATable.class);
加入b=a.加入(“b”);
连接b2=a.连接(“b”);
标准。其中(cb.or)(
cb.和(
cb.equal(b.get(“status”)、cb.literal(status.INITIAL)),
a、 get(“main”).isNull(),
cb.和(
cb.equal(b2.get(“status”)、cb.literal(status.INITIAL)),
cb.equal(b2.get(“主”),a)
)));
标准。多重选择(a.get(“id”)、b.get(“状态”);

请告诉我们您尝试了什么。对不起,我不能接受这个答案。虽然它非常详细,并且查询与我的查询相当,但这不是我想要的。我查询中的全部要点是重用exists查询(子查询)中主查询的
规范。我想这样做,因为用你的方式重写它需要很多代码。此外,主查询和子查询将几乎相同,因此这是我使用
exists
的另一个要点。谢谢你的贡献!回想起来,我可能没有仔细研究过您的解决方案。这看起来对我的案子有用。很抱歉之前的评论。我接受你的回答。非常感谢。