Spring Data JPA ค้นหาโดยคุณสมบัติวัตถุฝังตัว


101

ฉันต้องการเขียนลายเซ็นเมธอดอินเทอร์เฟซ Spring Data JPA ที่จะช่วยให้ฉันค้นหาเอนทิตีที่มีคุณสมบัติของอ็อบเจ็กต์ฝังตัวในเอนทิตีนั้น ไม่มีใครรู้ว่าเป็นไปได้หรือไม่และถ้าเป็นเช่นนั้นได้อย่างไร

นี่คือรหัสของฉัน:

@Entity
@Table(name = "BOOK_UPDATE_QUEUE", indexes = { uniqueConstraints = @UniqueConstraint(columnNames = {
        "bookId", "region" }, name = "UK01_BOOK_UPDATE_QUEUE"))
public class QueuedBook implements Serializable {

    @Embedded
    @NotNull
    private BookId bookId;

    ...

}

@Embeddable
public class BookId implements Serializable {

    @NotNull
    @Size(min=1, max=40)
    private String bookId;

    @NotNull
    @Enumerated(EnumType.STRING)
    private Region region;

    ...

}

public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> {

    //I'd like to write a method like this, but can't figure out how to search by region,
    //when region is actually a part of the embedded BookId
    Page<QueuedBook> findByRegion(Region region, Pageable pageable);

}

ฉันสามารถเขียนข้อความค้นหาโดยใช้ Spring Data ได้หรือไม่


4
ไม่findByBookIdRegion(Region region, Pageable pageable)ทำเคล็ดลับ?
Oliver Drotbohm

2
ใช่นั่นเป็นอย่างนั้น ฉันไม่พบเอกสารของที่ใดเลย มันซ่อนอยู่หรือโดยนัยที่ฉันไม่เห็น?
CorayThan

เปลี่ยนเป็นคำตอบและเพิ่มลิงก์ไปยังส่วนที่เกี่ยวข้องของเอกสารอ้างอิง
Oliver Drotbohm

คำตอบ:


145

ชื่อเมธอดนี้ควรใช้เคล็ดลับ:

Page<QueuedBook> findByBookIdRegion(Region region, Pageable pageable);

ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ในส่วนเกี่ยวกับการสืบค้นจากเอกสารอ้างอิง


11
จะเกิดอะไรขึ้นถ้าฉันมีรายการ Embeddable? หรือคอลเลกชันองค์ประกอบ?
user962206

ถ้าเราต้องการค้นหา findBy ด้วย 3 preperty แล้วจะเป็น syntax อะไร? มันเหมือน findByPro1AndPro2AndPro3 หรือเปล่า
surendrapanday

ข้อความค้นหาดังกล่าวส่งผลให้เกิดการรวมภายในเสมอหรือไม่ ฉันกำลังทำOne findByIdAndTwoId(Long oneId, Long twoId);และผลลัพธ์ในแบบสอบถามของแบบฟอร์ม:select ...... from one one_ left outer join two two_ on one_.two_id = two_.id where one_id = ? and two_.id = ?
TroJaN

44

ข้างต้น - findByBookIdRegion () ไม่ได้ผลสำหรับฉัน ต่อไปนี้ใช้ได้กับ String Data JPA รุ่นล่าสุด:

Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);

3
กรณีของคุณอาจเกี่ยวข้องกับความคลุมเครือตามที่กล่าวไว้ที่docs.spring.io/spring-data/jpa/docs/current/reference/html/…
Marcello de Sales

9

หากคุณใช้ BookId เป็นคีย์หลักแบบรวมอย่าลืมเปลี่ยนอินเทอร์เฟซของคุณจาก:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, Long> {

ถึง:

public interface QueuedBookRepo extends JpaRepository<QueuedBook, BookId> {

และเปลี่ยนคำอธิบายประกอบ @Embedded เป็น @EmbeddedId ในคลาส QueuedBook ของคุณดังนี้:

public class QueuedBook implements Serializable {

@EmbeddedId
@NotNull
private BookId bookId;

...

1

ตามที่ฉันบอก Spring ไม่ได้จัดการทุกกรณีอย่างสบายใจ ในกรณีของคุณสิ่งต่อไปนี้ควรทำตามเคล็ดลับ

Page<QueuedBook> findByBookIdRegion(Region region, Pageable pageable);  

หรือ

Page<QueuedBook> findByBookId_Region(Region region, Pageable pageable);

อย่างไรก็ตามยังขึ้นอยู่กับรูปแบบการตั้งชื่อของเขตข้อมูลที่คุณมีใน@Embeddableชั้นเรียนของคุณ

เช่นฟิลด์ต่อไปนี้อาจใช้ไม่ได้ในรูปแบบใด ๆ ที่กล่าวถึงข้างต้น

private String cRcdDel;

ฉันลองกับทั้งสองกรณี (ดังต่อไปนี้) และไม่ได้ผล (ดูเหมือนว่า Spring จะไม่จัดการกับรูปแบบการตั้งชื่อประเภทนี้ (เช่นกับตัวพิมพ์ใหญ่หลายตัวโดยเฉพาะในตัวอักษรเริ่มต้น - ตัวอักษรตัวที่ 2 (ไม่แน่ใจว่าเป็น กรณีเดียว)

Page<QueuedBook> findByBookIdCRcdDel(String cRcdDel, Pageable pageable); 

หรือ

Page<QueuedBook> findByBookIdCRcdDel(String cRcdDel, Pageable pageable);

เมื่อฉันเปลี่ยนชื่อคอลัมน์เป็น

private String rcdDel;

โซลูชันต่อไปนี้ของฉันทำงานได้ดีโดยไม่มีปัญหาใด ๆ :

Page<QueuedBook> findByBookIdRcdDel(String rcdDel, Pageable pageable); 

หรือ

Page<QueuedBook> findByBookIdRcdDel(String rcdDel, Pageable pageable);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.