Spring Data: รองรับ“ delete by” ไหม


104

ฉันใช้ Spring JPA สำหรับการเข้าถึงฐานข้อมูล ฉันสามารถค้นหาตัวอย่างเช่น findByName และ countByName ซึ่งฉันไม่ต้องเขียนวิธีการใช้งานใด ๆ ฉันหวังว่าจะพบตัวอย่างสำหรับการลบกลุ่มของระเบียนตามเงื่อนไขบางประการ

Spring JPA รองรับการลบเหมือน deleteByName หรือไม่ ตัวชี้ใด ๆ ได้รับการชื่นชม

ขอแสดงความนับถือและขอบคุณ

คำตอบ:


190

คำตอบที่ไม่รองรับ (Spring Data JPA <= 1.6.x) :

@Modifyingคำอธิบายประกอบเพื่อช่วยเหลือ คุณจะต้องระบุพฤติกรรม SQL ที่กำหนดเองของคุณแม้ว่า

public interface UserRepository extends JpaRepository<User, Long> {
    @Modifying
    @Query("delete from User u where u.firstName = ?1")
    void deleteUsersByFirstName(String firstName);
}

อัปเดต:

ในรุ่นที่ทันสมัยของฤดูใบไม้ผลิข้อมูล JPA (> = 1.7.x) รากศัพท์แบบสอบถามสำหรับdelete, removeและcountการดำเนินงานที่สามารถเข้าถึงได้

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}

2
@AndreyAtapin Downvote เพราะมันไม่ใช่คำตอบที่ดีอีกต่อไป อาจจะลบทิ้ง? ข้อบกพร่องอย่างหนึ่งของ stackoverflows คือการจัดการการเปลี่ยนแปลงเวอร์ชัน / การแก้ไขข้อบกพร่องที่เกี่ยวข้องกับไลบรารีที่เป็นปัญหา
Ben George

1
@webgeek ฉันเคยแก้ปัญหานี้ด้วยDELETE FROM x WHERE id = ?1 or parent_id = ?1. Btw ตรวจสอบให้แน่ใจว่าคุณไม่มีประเภทparent__id(คุณมีเส้นประต่ำสองเท่าโดยตั้งใจหรือไม่?) ทำไมคุณถึงใช้ตัวเลือกการสืบค้นแบบเนทีฟ
Andrey Atapin

4
แม้ว่าฉันจะใช้ 1.7.4 คำอธิบายประกอบ @Transactional ก็เป็นสิ่งจำเป็นเหนือวิธีการค้นหาเพื่อให้การลบสำเร็จ
gokhansari

40
โดยทั่วไปในแอปพลิเคชันคุณจะมีคลาส / วิธีการ @ Service และสิ่งเหล่านี้จะเรียกที่เก็บ และวิธีการสาธารณะ @ Service ควรเป็นเมธอดที่มีเครื่องหมาย @ Transactional เนื่องจากธุรกรรมใช้ Use Case หมายถึงกรณีการใช้งานจำเป็นต้องกระทำหรือย้อนกลับอย่างสมบูรณ์ ไม่ใช่แต่ละเมธอด Repository ดังนั้นโปรดอย่าใช้ @ Transactional ในเมธอด Repository แต่ใช้วิธีการบริการที่ใช้ที่เก็บ
user1567291

1
การทำ @Transactional ที่ repo หมายถึงบริการภายในหากคุณเรียก repo หลายครั้งแต่ละครั้งจะมีธุรกรรมที่แตกต่างกันดังนั้นการย้อนกลับภายใน 1 แบบสอบถาม หากคุณให้บริการที่ระดับบริการฟังก์ชันทั้งหมดของคุณจะย้อนกลับเมื่อเกิดข้อผิดพลาดใด ๆ
P Satish Patro

80

การสร้างคำสั่งลบโดยใช้ชื่อเมธอดที่กำหนดได้รับการสนับสนุนเริ่มต้นด้วยเวอร์ชัน1.6.0.RC1ของ Spring Data JPA คำหลักremoveและdeleteได้รับการสนับสนุน ในฐานะที่เป็นค่าส่งกลับเราสามารถเลือกระหว่างตัวเลขหรือรายการของเอนทิตีที่ถูกลบออก

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);

7

ถ้าคุณดูที่รหัสที่มาของฤดูใบไม้ผลิข้อมูล JPA และโดยเฉพาะอย่างยิ่งระดับคุณจะเห็นว่าเป็นความพยายามอินสแตนซ์PartTreeJpaQuery PartTreeภายในคลาสนั้นมีนิพจน์ทั่วไปต่อไปนี้

private static final Pattern PREFIX_TEMPLATE = Pattern.compile("^(find|read|get|count|query)(\\p{Lu}.*?)??By")

ควรระบุสิ่งที่อนุญาตและสิ่งที่ไม่อนุญาต

แน่นอนว่าถ้าคุณพยายามเพิ่มวิธีดังกล่าวคุณจะเห็นว่ามันใช้ไม่ได้ผลและคุณจะได้รับ stacktrace แบบเต็ม

ฉันควรทราบว่าฉันกำลังใช้ดูเวอร์ชัน1.5.0.RELEASEของ Spring Data JPA


7

2 วิธี: -

คำค้นหาที่กำหนดเอง 1 รายการแรก

@Modifying
@Query("delete from User where firstName = :firstName")
void deleteUsersByFirstName(@Param("firstName") String firstName);

2nd one JPA Query โดยวิธีการ

List<User> deleteByLastname(String lastname);

เมื่อคุณค้นหาด้วยวิธีการ (วิธีที่ 2) จะทำการรับสายก่อน

select * from user where last_name = :firstName

จากนั้นมันจะโหลดขึ้นมาใน List จากนั้นมันจะเรียกลบ id ทีละตัว

delete from user where id = 18
delete from user where id = 19

ขั้นแรกดึงรายการวัตถุจากนั้นวนซ้ำเพื่อลบ id ทีละรายการ

แต่ตัวเลือกแรก (ข้อความค้นหาที่กำหนดเอง)

เป็นเพียงแบบสอบถามเดียวซึ่งจะลบทุกที่ที่มีค่าอยู่

ผ่านลิงค์นี้ด้วยhttps://www.baeldung.com/spring-data-jpa-deleteby


1
ขอบคุณสำหรับข้อมูล!
curious1

2

หากคุณจะใช้วิธีการลบที่กำหนดไว้ล่วงหน้าตามที่กำหนดโดย spring JPA โดยตรงดังนั้นด้านล่างสองคิวรีจะถูกดำเนินการโดยเฟรมเวิร์ก

  • ก่อนอื่นให้รวบรวมข้อมูล (เช่น id และคอลัมน์อื่น ๆ ) โดยใช้โดยดำเนินการเลือกคิวรีพร้อมลบคิวรีโดยที่อนุประโยค

  • หลังจากได้รับ resultSet ของแบบสอบถามแรกแล้วคิวรีลบที่สองจะถูกเรียกใช้สำหรับ id ทั้งหมด (ทีละรายการ)

    หมายเหตุ: นี่ไม่ใช่วิธีที่เหมาะสมที่สุดสำหรับแอปพลิเคชันของคุณเนื่องจากจะมีการดำเนินการสืบค้นจำนวนมากสำหรับแบบสอบถามลบ MYSQL เดียว

นี่เป็นอีกวิธีหนึ่งที่ได้รับการปรับให้เหมาะสมที่สุดสำหรับการลบโค้ดแบบสอบถามเนื่องจากมีคิวรีลบเพียงรายการเดียวเท่านั้นที่จะดำเนินการโดยใช้วิธีการที่กำหนดเองด้านล่าง



@NamedNativeQueries({

@NamedNativeQuery(name = "Abc.deleteByCreatedTimeBetween",
            query = "DELETE FROM abc WHERE create_time BETWEEN ?1 AND ?2")
    ,

    @NamedNativeQuery(name = "Abc.getByMaxId",
            query = "SELECT max(id) from abc")
})

@Entity
public class Abc implements Serializable {

}

@Repository
public interface AbcRepository extends CrudRepository {

    int getByMaxId();

    @Transactional
    @Modifying
    void deleteByCreatedTimeBetween(String startDate, String endDate);
}


2

ระมัดระวังเมื่อคุณใช้แบบสอบถามที่ได้รับมาสำหรับการลบแบทช์ ไม่ใช่สิ่งที่คุณคาดหวัง: DeleteExecution


สวัสดี. หากคุณกำลังชี้ RBAR (row by agonizing row) คุณช่วยเพิ่มคำตอบนั้นได้ไหม (และฉันจะโหวตให้) ฉันพอจะเดาออกว่าคุณกำลังชี้ให้เห็นอะไรที่นี่
granadaCoder

0

ใช่รองรับวิธี deleteBy หากต้องการใช้คุณต้องใส่คำอธิบายประกอบวิธีด้วย @Transactional


0

นี่ตาม 2 เซ็นต์ของฉัน คุณยังสามารถใช้คำค้นหาเนทีฟเช่น:

@Modifying
@Query(value="delete from rreo r where r.cod_ibge = ?1 and r.exercicio= ?2", nativeQuery = true)
void deleteByParameters(Integer codIbge, Integer exercicio);

0
@Query(value = "delete from addresses u where u.ADDRESS_ID LIKE %:addressId%", nativeQuery = true)
void deleteAddressByAddressId(@Param("addressId") String addressId);

2
ยินดีต้อนรับสู่ Stack Overflow ก่อนที่จะตอบคำถามเก่าที่มีคำตอบที่เป็นที่ยอมรับ (มองหา✓สีเขียว) รวมทั้งคำตอบอื่น ๆ ให้แน่ใจว่าคำตอบของคุณเพิ่มสิ่งใหม่หรือเป็นประโยชน์อย่างอื่นที่เกี่ยวข้องกับคำถามเหล่านี้ นอกจากนี้การโพสต์โค้ดโดยไม่มีคำอธิบายใด ๆ ก็ไม่เป็นประโยชน์เนื่องจากไม่ได้อธิบายว่าทำไมหรือตอบคำถามได้อย่างไร โปรดใส่คำอธิบายสำหรับโค้ดของคุณเพื่อปรับปรุงคุณภาพโพสต์ของคุณ โปรดดูที่ฉันจะเขียนคำตอบที่ดีได้อย่างไร .
Ivo Mori
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.