วิธีเขียนแบบสอบถามด้วยคอลัมน์จำนวนเพิ่มเติมโดยใช้ JPA Criteria Builder

Aug 18 2020

ฉันกำลังดิ้นรนที่จะเขียนแบบสอบถาม JPA ที่จะส่งคืนวัตถุ P ทั้งหมดที่อยู่ในฐานข้อมูลและถัดจากพวกเขาฉันต้องการนับลูก S ของพวกเขาที่มีคุณสมบัติ A = 1

แบบสอบถาม SQL

เลือก p. *, (Select count (s.id) จาก 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);

คำตอบ

JLazar0 Aug 19 2020 at 09:57
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){
    [...]
}

คุณจะต้องเปลี่ยนเอนทิตีของคุณเพื่อจับคู่ความสัมพันธ์อย่างถูกต้องเป็นแบบสองทิศทางและขี้เกียจในการปรับปรุงประสิทธิภาพดังนี้:

PTable

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

เสถียร

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