Lingkungan Pengembangan Artikel ini: Spring-Boot: 2.0.3.Release + Java1.8
Mengapa melakukannya
Penghapusan lunak: Artinya, tidak ada operasi penghapusan nyata yang dilakukan. Karena adanya pengikatan (kunci asing) antara entitas kami, menghapus beberapa data akan menyebabkan data lain yang tidak lengkap. Misalnya, guru di kelas komputer 1801 adalah Zhang San. Pada saat ini, jika kita menghapus Zhang San, maka ketika kita menanyakan Kelas Komputer 1801, karena Zhang San tidak ada lagi, kita akan melaporkan kesalahan EntityNotFound. Tentu saja, dalam database dengan kendala kunci asing, jika Zhang San adalah seorang guru di kelas 1801, maka kami akan secara langsung menghapus Zhang San dan melaporkan pengecualian yang mengikat. Dengan kata lain, perilaku menghapus secara langsung Zhang San tidak dapat dieksekusi.
Tetapi kadang -kadang, kita memiliki kebutuhan untuk menghapusnya. Misalnya, seorang karyawan pergi dan kemudian kami ingin menghapus karyawan dalam manajemen karyawan. Namun: Karyawan memiliki riwayat dalam tabel data. Sebagai contoh, kami mencatat bahwa struktur data semester kedua 2017 adalah Zhang Sanjiao. Kemudian, karena adanya kendala, kesalahan pengikatan akan dilaporkan ketika menghapus Zhang San. Dengan kata lain: rasa malu yang harus dihapus tetapi tidak dapat dihapus.
Ini menggunakan penghapusan lunak yang disebutkan dalam artikel ini. Yang disebut penghapusan lunak berarti bahwa saya tidak benar-benar menghapus data dalam tabel data, tetapi sebaliknya menambahkan tanda ke catatan apakah akan menghapusnya.
Spring JPA mendukung penghapusan lunak, kita dapat menemukan lebih banyak artikel dengan kualitas yang baik untuk menyelesaikan masalah ini. Langkah -langkah umum adalah: 1. Tambahkan @sqldelete ("Perbarui xxxx set deleted = 1 where id = ?")。2.加入@Where(clause = "deleted = false") . Tapi solusi ini tidak sempurna. Secara khusus dimanifestasikan dalam:
Mari kita ambil Zhang San sebagai guru di kelas 1801 sebagai contoh.
Setelah menambahkan anotasi, kita memang bisa berhasil menghapus Zhang San. Setelah operasi penghapusan, kami memeriksa tabel data dan catatan Zhang San memang masih ada. Tetapi pada saat ini, jika kita melakukan all atau kueri page , kita akan mendapatkan kesalahan 500 EntiyNotFound . Ini karena selama semua kueri, JPA secara otomatis menambahkan parameter kueri di @Where . Karena deleted = true dari data yang terkait, pengecualian bahwa entitas terkait tidak ditemukan.
Tetapi faktanya adalah: Meskipun entitas dihapus, masih ada, dan kami ingin menerapkannya pada permintaan asosiasi. Tidak diharapkan bahwa ia akan memiliki pengecualian 500 EntiyNotFound .
Solusi dari artikel ini mengimplementasikan:
Larutan
Pelaksanaan
inisialisasi
Buat tiga entitas baru: ClazzTest, Clazz, Teacher , dan buat entitas kelas abstrak BaseEntity baru. Di mana ClazzTest digunakan untuk menunjukkan pengecualian yang terjadi saat menggunakan @Where(clause = "deleted = false") .
Paket com.mengyunzhi.springbootsamplecode.softdelete.entity; import javax.persistence.mappedSuperclass; @mappedSuperclasspublic kelas abstrak baseEntity {private boolean dihapus = false; // setter and getter} Paket com.mengyunzhi.springbootsamplecode.softdelete.entity; impor org.hibernate.annotations.sqldelete; import javax.persistence.entity; import javax.persistence.generatedValue; impor javax. `Klass` Set dihapus = 1 di mana id =?") Kelas publik Klass memperluas baseEntity {@id @GeneratedValue Private Long ID; nama string pribadi; // setter and getter} @Entitas @sqldelete (sql = "perbarui` klass_test` set dihapus = 1 di mana id =? ") @Di mana (klausa =" dihapus = false ") kelas publik Klasstest memperluas baseEntity {@id @id @GeneratedValue Private Long ID; nama string pribadi;} Tulis ulang crudrepository
Paket com.mengyunzhi.springbootsamplecode.softdelete.core; impor org.springframework.data.jpa.repository.query; impor org.springframework.data.repository.crudrepository; impor org.spramework.data.repository.rudrepository; impor org.spramework. javax.transaction.transactional; impor java.util.optional;/*** Terapkan soft delete* default @where (klausa = "dihapus = 0") akan menyebabkan pengecualian objeknotfound ketika kueri yang terkait dilakukan di dalam hibernate* Refine antarmuka di sini* referensi: referensi: ketika kueri terkait dilakukan di dalam hibernate* Referensi di sini* referensi* Referensi: https://stackoverflow.com/questions/1932357/handling-soft-deletes-with-spring-jpa/22202469 * @author menyunzhi tim pengembangan hebei> @norepositorybeanplic softdelety softdeletory {norepositorybeanplic softdelety {norepositorybean @Override @transactional @Query ("Pilih e dari #{ #entityName} e di mana e.id =? 1 dan e.deleted = false") opsional <t> findById (id id); @Override @transactional default boolean existsbyid (id id) {return findById (id) .ispresent (); } @Override @transactional @Query ("Pilih e dari #{ #entityName} e di mana e.deleted = false") iterable <t> findAll (); @Override @transactional @Query ("Pilih e dari #{ #entityName} e di mana e.id in? 1 dan e.deleted = false") iterable <t> findAllById (ITerable <d> ids); @Override @transactional @Query ("Pilih hitungan (e) dari #{ #entityName} e di mana e.deleted = false") long count ();} Buat kelas gudang baru
Mewarisi Crudrepository Spring.
/*** Kelas* @author Panjie*/Antarmuka Publik KlassRepository Memperluas SoftDeleteCrudrepository <Klass, Long> {} Antarmuka publik KlasStestrepository memperluas softdeletecrudrepository <klasstest, long> {} TeacherRepository antarmuka publik memperluas crudrepository <guru, long> {} tes
Paket com.mengyunzhi.springbootsamplecode.softdelete.repository; import com.mengyunzhi.springbootsamplecode.softdelete.entity.klasse.softdeleety.entity.entity.entity ;klastests ;klastity.softdelety.entity.entity com.mengyunzhi.springbootsamplecode.softdelete.entity.teacher; impor org.assertj.core.api.assions; impor org.junit.test; impor org.junit.runner.runwith; impor org.slf4j.logger; impor; Impor; logrger; logrger; lacrger; lacrger; logrger; lacrger; lacrger; lacrger; legorjger; legrger; legorjger; legrger; legrger; legrger; legrger; legrger; legrger; logrger; logrger; logrger; logrger; log.lger; org.springframework.beans.factory.annotation.Autowired; impor org.springframework.boot.test.context.springboottest; impor org.springframework.orm.jpa.jpaobjectretrieValfalMailexception; impor.orm.jpa.jpaoBectretrieVaileexception; orgrunnework.junnework.junnework.junnework.junnex.junex.junx.junex.junnx.junex.junx.junex.junnx.junex.junex.junnex.junex.junx.junex.junx.junex.junnx.junex.junex.spring.junnx.junx.pramex.junex.spring java.util.list; import java.util.optional;/** * @author Panjie */@springboottest@runwith (springrunner.class) kelas publik TeacherRepositoryTest {private final static Logger = loggerFactory.getLogger (TeacherRepositorytest.claskass); @Autowired klassrepository klassRepository; @Autowired klasstestrepository klasstestrepository; @Autowired TeacherRepository TeacherRepository; @Test public void findById () {logger.info ("Buat guru baru dengan klass dan klasstest"); Klass klass = klass baru (); klassrepository.save (Klass); Klasstest Klasstest = Klasstest baru (); klasstestrepository.save (Klasstest); Guru guru = guru baru (); Teacher.SetKlass (Klass); guru.setklasstest (Klasstest); TeacherRepository.Save (guru); Logger.info ("Cari guru, tegaskan bahwa entitas itu ditemukan, dan tidak ada pengecualian terjadi"); Opsional <teacher> TeacherOpsional = TeacherRepository.findById (Teacher.getId ()); Assertions.assertThat (TeacherOptional.get ()). IsNotnull (); Logger.info ("Hapus Klass yang terkait, lalu cari entitas guru, tegaskan bahwa entitas itu ditemukan, tidak ada pengecualian terjadi. Nyatakan bahwa masih ada entitas Klass yang dihapus dalam entitas guru"); klassrepository.deletebyid (klass.getId ()); TeacherOpsional = TeacherRepository.findById (Teacher.GetID ()); Assertions.assertThat (TeacherOptional.get ()). IsNotnull (); Assertions.assertThat (TeacherOptional.get (). GetKlass (). GetId ()). IsEqualto (klass.getid ()); Logger.info ("Cari daftar guru, tidak ada pengecualian terjadi. Nyatakan bahwa ada catatan entitas Klass yang dihapus dalam entitas guru"); Daftar <Gell Teacher> TeacherList = (Daftar <Gell Teacher>) TeacherRepository.Findall (); untuk (guru guru1: guru) {assertions.assertThat (guru1.getklass (). getId ()). isequalto (klass.getid ()); } Logger.info ("Hapus Klasstest yang terkait, lalu lihat entitas guru, tegaskan bahwa Klasstest yang dihapus ditemukan"); klasstestrepository.deletebyid (klasstest.getId ()); TeacherOpsional = TeacherRepository.findById (Teacher.GetID ()); Assertions.assertThat (TeacherOptional.get ()). IsNotnull (); Assertions.assertThat (TeacherOptional.get (). Getklasstest (). GetId ()). IsEqualto (klasstest.getid ()); Logger.info ("Cari daftar guru lagi, tegaskan bahwa jpaobjectretrievalfailureException akan terjadi (pengecualian EntityNotFound ditangkap, dienkapsulasi dan dilemparkan)"); Boolean CatchException = false; Coba {TeacherRepository.Findall (); } catch (jpaobjectrievalfalfailureException e) {catchException = true; } Assertions.assertThat (catchException) .istrue (); }} Meringkaskan
Saat menggunakan anotasi @sqldelete default dan @where, data JPA dapat menangani metode findById () dengan baik, tetapi gagal untuk menangani metode FindAll () dengan baik. Di sini, kami telah mengimplementasikan metode penulisan ulang metode crunrepository. Ketika kami akan melakukan kueri dasar, kami menggunakan metode khusus kami untuk menambahkan dihapus = true. Ketika JPA melakukan kueri asosiasi, karena kami tidak mengatur anotasi @di mana, semua data akan diminta, sehingga menghindari pengecualian yang kadang -kadang terjadi ketika kueri foundall () dilakukan.
Dalam artikel ini, kami hanya memberikan beberapa contoh kode.
Jika Anda memerlukan kode lengkap, silakan klik: https://github.com/mengyunzhi/springbootsamplecode/tree/master/softdelete.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.