Data Musim Semi: "hapus oleh" didukung?

99

Saya menggunakan Spring JPA untuk akses database. Saya dapat menemukan contoh seperti findByName dan countByName, yang saya tidak perlu menulis implementasi metode apa pun. Saya berharap menemukan contoh untuk menghapus sekelompok record berdasarkan beberapa kondisi.

Apakah Spring JPA mendukung deleteByName-like delete? Pointer apa pun dihargai.

Salam dan terima kasih.

penasaran1
sumber

Jawaban:

184

Jawaban yang tidak berlaku lagi (Spring Data JPA <= 1.6.x) :

@Modifyinganotasi untuk menyelamatkan. Anda harus menyediakan perilaku SQL kustom Anda.

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

Memperbarui:

Dalam versi modern dari derivasi kueri JPA (> = 1.7.x) Spring Data delete, removedan countoperasi dapat diakses.

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}
Andrey Atapin
sumber
2
@AndreyAtapin Downvote karena itu bukan lagi jawaban yang bagus. Mungkin menghapusnya? Salah satu kekurangan stackoverflows adalah menangani perubahan versi / perbaikan bug yang terkait dengan pustaka yang dimaksud.
Ben George
1
@webgeek, saya biasa memecahkan masalah ini dengan DELETE FROM x WHERE id = ?1 or parent_id = ?1. Btw, pastikan Anda tidak memiliki tipe parent__id(apakah Anda sengaja memiliki tanda hubung rendah ganda?). Mengapa Anda menggunakan opsi kueri asli?
Andrey Atapin
4
Bahkan saya menggunakan 1.7.4, anotasi @Transactional diperlukan di atas metode kueri agar penghapusan berhasil
gokhansari
40
Biasanya, dalam sebuah aplikasi, Anda akan memiliki @ Kelas / metode layanan dan mereka akan memanggil Repositori. Dan metode publik @ Service harus menjadi metode yang bertanda @ Transaksional karena transaksinya berbasis Use Case. Artinya kasus penggunaan harus sepenuhnya dilakukan atau dikembalikan. Tidak setiap individu metode Repositori. Jadi TOLONG JANGAN gunakan metode @ Transactional on Repository. Namun pada metode Service yang menggunakan repositori.
pengguna1567291
1
Membuat @Transactional pada repo berarti dalam layanan jika Anda memanggil repo beberapa kali masing-masing akan memiliki transaksi yang berbeda, jadi kembalikan dalam 1 query. Jika Anda memberikan di tingkat layanan, seluruh fungsi Anda akan dimundurkan jika ada kesalahan.
P Satish Patro
78

Penurunan kueri penghapusan menggunakan nama metode yang diberikan didukung mulai dengan versi 1.6.0.RC1 dari Spring Data JPA. Kata kunci removedan deletedidukung. Sebagai nilai pengembalian, seseorang dapat memilih antara nomor atau daftar entitas yang dihapus.

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);
Christoph Strobl
sumber
7

Jika Anda melihat kode sumber dari Spring Data JPA, dan khususnya PartTreeJpaQuerykelasnya, Anda akan melihat bahwa mencoba untuk memberi contoh PartTree. Di dalam kelas itu ekspresi reguler berikut

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

harus menunjukkan apa yang diperbolehkan dan apa yang tidak.

Tentu saja jika Anda mencoba menambahkan metode seperti itu, Anda akan benar-benar melihat bahwa metode tersebut tidak berfungsi dan Anda mendapatkan pelacakan tumpukan penuh.

Saya harus mencatat bahwa saya menggunakan melihat versi 1.5.0.RELEASESpring Data JPA

geoand
sumber
6

2 cara: -

Kueri Kustom pertama

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

Kueri JPA kedua berdasarkan metode

List<User> deleteByLastname(String lastname);

Ketika Anda pergi dengan query dengan metode (cara ke-2) pertama-tama akan melakukan panggilan get

select * from user where last_name = :firstName

Kemudian itu akan memuatnya dalam Daftar Kemudian itu akan memanggil delete id satu per satu

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

Pertama ambil daftar objeknya, kemudian for loop untuk menghapus id satu per satu

Tapi, opsi pertama (kueri khusus),

Itu hanya satu kueri. Itu akan menghapus di mana pun nilai itu ada.

Buka tautan ini juga https://www.baeldung.com/spring-data-jpa-deleteby

P Satish Patro
sumber
1
Terimakasih atas infonya!
penasaran1
2

Jika Anda akan menggunakan metode penghapusan yang ditentukan sebelumnya seperti yang disediakan langsung oleh JPA musim semi, maka di bawah dua kueri akan dieksekusi oleh kerangka kerja.

  • Pertama-tama kumpulkan data (seperti id dan kolom lain) menggunakan dengan mengeksekusi kueri pemilihan dengan kueri hapus di mana klausa.

  • kemudian setelah mendapatkan resultSet dari query pertama, query delete kedua akan dijalankan untuk semua id (satu per satu)

    Catatan: Ini bukan cara yang dioptimalkan untuk aplikasi Anda karena banyak kueri akan dieksekusi untuk kueri penghapusan MYSQL tunggal.

Ini adalah cara lain yang dioptimalkan untuk menghapus kode kueri karena hanya satu kueri penghapusan yang akan dijalankan dengan menggunakan metode yang disesuaikan di bawah ini.



@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);
}
Suneet Khurana
sumber
1

Berhati-hatilah saat Anda menggunakan kueri turunan untuk penghapusan batch. Ini bukan yang Anda harapkan: DeleteExecution

Andrey Ofim
sumber
Hai. Jika Anda menunjukkan RBAR (baris demi baris yang menyakitkan), dapatkah Anda menambahkannya ke jawaban Anda? (dan saya akan memberi suara positif). Saya agak menebak-nebak apa yang Anda tunjukkan di sini.
granadaCoder
0

Ya, metode deleteBy didukung Untuk menggunakannya, Anda perlu membuat anotasi metode dengan @Transactional

amoljdv06.dll
sumber