【问题标题】:How to write query with additional count column using JPA Criteria Builder如何使用 JPA Criteria Builder 编写带有附加计数列的查询
【发布时间】:2020-12-07 19:53:58
【问题描述】:

我正在努力编写一个 JPA 查询,该查询将返回数据库中的所有 P 对象,并且在它们旁边我想计算其具有 propertyA = 1 的 S 子对象。

SQL 查询

Select p.*, (Select count(s.id) from s_table s WHERE p.id = s.p_id 和 s.propertyA = 1) 来自 p_table p

映射:

@Entity
@Table(name = "t_table")
public class PTable{
    @Id
    private String id;

    @Version
    private Long version;

    private String subject;
   
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
    @JoinColumn(name = "p_id", referencedColumnName = "id")
    private Set<STable> sSet = new HashSet<>();
}
 
@Entity
@Table(name = "s_table")
public class STable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "p_id")
    private String pId;
  
    private String propertyA;
}

另外,您想指出任何在 JPA 中编写复杂查询的好教程吗?

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<PTable> q = cb.createQuery(PTable.class);
Root<PTable> c = q.from(PTable.class);

【问题讨论】:

  • 您是否在实体定义中映射了连接关系?给他们看。为什么不使用像SELECT s.*, count(p.id) FROM p_table p JOIN s_table s ON p.id = s.p_id WHERE p.propertyA = 1 GROUP BY s.id 这样的普通sql 查询。这样的查询更容易变成 JPQL 和 JPA CriteriaQuery
  • 我添加了映射。这种映射已经存在于代码中。我必须创建这样的查询。
  • 不清楚,考虑到您可能希望选择 PTable 与 count(STable) 的关系?
  • 哦..对不起,我更正了描述。结果,我想拥有数据库中的所有 P 对象,并且在它们旁边我想计算其具有 propertyA = 1 的 S 子对象。

标签: hibernate jpa jpa-2.0 criteria-api


【解决方案1】:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<MyPojo> cq = cb.createQuery(MyPojo.class);

Root<PTable> rootPTable = cq.from(PTable.class);
Join<PTable, STable> joinSTable = rootPTable.join(PTable_.sSet);

Subquery<Long> sqCount = cq.subquery(Long.class);
Root<STable> sqRootSTable = sqCount.from(STable.class);
Join<STable, PTable> sqJoinPTable = sqRootSTable.join(STable_.pSet);

sqCount.where(cb.and(
    cb.equal(sqJoinPTable.get(PTable_.id),rootPTable.get(PTable_.id)),
    cb.equal(sqRootSTable.get(STable_.propertyA),"1")));

sqCount.select(cb.count(sqRootSTable));

cq.multiselect(
    rootPTable.get(PTable_.id),
    rootPTable.get(PTable_.version),
    rootPTable.get(PTable_.subject),
    joinSTable.get(STable_.id),
    sqCount.getSelection(),
);

您将需要一个 Pojo 来获取构造函数具有的结果,该结果与多选参数的顺序和类型匹配,如下所示:

public MyPojo(String pId, Long version, String subject, Long sId, Long count){
    [...]
}

您还必须更改实体以正确映射关系、双向和惰性以提高性能,如下所示:

表格

@OneToMany(mappedBy="p",fetch = FetchType.LAZY)
private Set<STable> sSet;

稳定

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="id")
private PTable p;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 2021-01-20
    • 2011-08-01
    • 1970-01-01
    相关资源
    最近更新 更多