Die Entwicklungsumgebung dieses Artikels: Springboot: 2.0.3.Release + Java1.8
Warum zu tun
Weiche Löschung: Das heißt, es wird kein wirklicher Löschvorgang durchgeführt. Aufgrund der Existenz von Bindungen (Fremdschlüssel) zwischen unseren Entitäten führt das Löschen einiger Daten zu unvollständigen anderen Daten. Zum Beispiel ist der Lehrer in der Computerklasse 1801 Zhang San. Wenn wir Zhang San zu diesem Zeitpunkt löschen, werden wir, wenn wir die Computerklasse 1801 abfragen, da Zhang San nicht mehr existiert, den EntityNotFound -Fehler melden. In einer Datenbank mit fremden Schlüsselbeschränkungen, wenn Zhang San in der Klasse 1801 Lehrer ist, werden wir natürlich Zhang San direkt löschen und eine verbindliche Ausnahme melden. Mit anderen Worten, das Verhalten des direkten Löschens von Zhang San kann nicht ausgeführt werden.
Aber manchmal müssen wir es löschen. Zum Beispiel verlässt ein Mitarbeiter und dann möchten wir den Mitarbeiter im Mitarbeitermanagement löschen. Der Mitarbeiter hat jedoch eine Geschichte in der Datentabelle. Zum Beispiel haben wir aufgezeichnet, dass die Datenstruktur des zweiten Semesters 2017 Zhang Sanjiao war. Aufgrund der Existenz von Einschränkungen wird ein Bindungsfehler beim Löschen von Zhang SAN gemeldet. Mit anderen Worten: Die Verlegenheit, dass es gelöscht werden sollte, kann aber nicht gelöscht werden.
Dies verwendet die in diesem Artikel erwähnte Soft -Löschung. Die sogenannte Soft-Löschung bedeutet, dass ich die Daten in der Datentabelle nicht wirklich lösche, sondern dem Datensatz eine Marke hinzufügen, ob sie sie löschen soll.
Spring JPA unterstützt eine weiche Löschung. Wir können mehr Artikel mit guter Qualität finden, um dieses Problem zu lösen. Die allgemeinen Schritte sind: 1. add @SQLDELETET ("XXXX set deleted = 1 where id = ?")。2.加入@Where(clause = "deleted = false") . Diese Lösung ist jedoch nicht perfekt. Speziell manifestiert in:
Nehmen wir Zhang San als Lehrer in Klasse 1801 als Beispiel.
Nach dem Hinzufügen der Annotation können wir Zhang San tatsächlich erfolgreich löschen. Nach dem Löschvorgang haben wir die Datentabelle überprüft und Zhang San's Record ist in der Tat noch da. Aber zu diesem Zeitpunkt, wenn wir all oder page ausführen, erhalten wir einen 500 EntiyNotFound -Fehler. Dies liegt daran, dass JPA bei aller Abfrage die Abfrageparameter automatisch in @Where hinzufügt. Aufgrund des deleted = true der zugehörigen Daten ist eine Ausnahme, die die zugehörige Entität nicht gefunden wird.
Tatsache ist jedoch: Obwohl die Entität gelöscht wird, ist es immer noch da, und wir möchten es auf die Assoziationsfrage anwenden. Es ist nicht zu erwarten, dass es eine 500 EntiyNotFound -Ausnahme gibt.
Die Lösung dieses Artikels implementiert:
Lösung
Durchführung
Initialisierung
Erstellen Sie drei neue Einheiten: ClazzTest, Clazz, Teacher und erstellen Sie eine neue Abstract -Einheit der BaseEntity abstrakt. Wo ClazzTest verwendet wird, um die Ausnahme zu demonstrieren, die bei der Verwendung @Where(clause = "deleted = false") auftritt.
Paket com.mengyunzhi.springbootSsamplecode.softDelete.Entity; Import Javax.Persistence.MappedSuperClass; // Setter und Getter}
Paket com.mengyunzhi.springbootSsamplecode.softDelete.Entity; import org.hibernate.Annotations.SQLDELETE; `klass` set deleted = 1 wobei id =?") öffentliche Klasse Klass erweitert BaseEntity {@ID @generatedValue Private Long ID; privater Zeichenfolge Name; // Setter und Getter} @Entity @sqldelete (SQL = "Aktualisieren Sie` klass_test` set deleted = 1 wobei id =? ") @Wobei (klausel =" deleted = false ") öffentliche Klasse Klasstest erweitert BaseEntity {@ID @generatedValue Private Long ID; privater Zeichenfolge Name;} Schreiben Sie Crudrepository neu
paket com.mengyunzhi.springbootSsamplecode.softdelete.core; import org.springframework.data.jpa.repository.query; javax.transaction.transactional; import java.util.optional;/*** Weiche Löschung anwenden* Standard @where (Klausel = "Deleted = 0") führt zu einer Ausnahme von ObjectNotfound, wenn eine zugehörige Abfrage in Hibernate* die Schnittstelle hier ausgeführt wird. https://stackoverflow.com/questions/19323557/handling-soft-deletes-with-Spring-jpa/22202469 * @author mengyunzhi Softwareentwicklungsteam von Hebei University of Technology */ @NorepositoryBeanpublic interface interface {trepository; @Override @Transactional @Query ("Wählen Sie E aus #{ #enttityName} e wob @Override @Transactional Standard Boolean existById (id id) {return findById (id) .iPresent (); } @Override @Transactional @Query ("Wählen Sie E aus #{ #EntityName} e wobei e.Deleted = false") iterable <t> findAll (); @Override @Transactional @Query ("Wählen Sie E aus #{ #enttityName} e wob @Override @Transactional @Query ("Wählen Sie count (e) aus #{ #EntityName} e wobei e.Deleted = false") Long Count ();}; Erstellen Sie eine neue Lagerklasse
Erben des Frühlings -Crudrepository.
/*** Klasse* @Author Panjie*/Public Interface KlassRepository erweitert SoftDeletteleCrudRepository <Klass, Long> {} Öffentliche Schnittstelle Klasstestrepository erweitert SoftDeletEcrudRepository <Klasstest, Long> {} Public Interface TeacherRepository erweitert Crudrepository <Lehrer, Long> {} prüfen
Paket com.mengyunzhi.springbootsamplecode.softdelete.repository; importieren com.mengyunzhi.springbootSsamplecode com.mengyunzhi.springbootSsamplecode.softDelete.entity.Teacher; org.springFramework.beans.factory.annotation.autowired; import org.springframework.boot.test.context.springboottest; import org.springFramework.orm.ORM.ORM.JPA.JPAOBJECTRETREVEURTEEXCTION; java.util.list; import java.util.optional;/** * @author panjie */@springboottest@runwith (springrunner.class) public class lehreRepositoryTest {private endgültige statische Logger logger = loggerfactory.getLogger (lehreerrepositorytest.class); @Autowired KlassRepository KlassRepository; @Autowired Klasstestrepository Klasstestrepository; @Autowired TeacherRrepository TeacherErrepository; @Test public void findById () {logger.info ("Erstellen Sie einen neuen Lehrer mit Klass und Klasstest"); Klass klass = new klass (); klassrepository.save (klass); Klasstest Klasstest = new klasstest (); klastestrepository.save (klasstest); Lehrer Lehrer = neuer Lehrer (); Teacher.Setklass (Klass); Teacher.Setklasstest (Klasstest); TeacherRepository.save (Lehrer); logger.info ("Suchen Sie nach dem Lehrer, behaupten, dass die Entität gefunden wurde und keine Ausnahme aufgetreten ist"); Optional <lehrer> lehreroptional = lehreErrepository.findbyId (lehrer.getId ()); AsSertions.AsSertThat (lernoptional.get ()). Isnotnull (); logger.info ("Löschen Sie den zugehörigen Klass, schauen Sie dann die Lehrereinheit nach, behaupten, dass das Unternehmen gefunden wurde, keine Ausnahme. Behauptet, dass es noch eine gelöschte Klas -Einheit in der Lehrereinheit gibt"); klassrepository.deletebyId (klass.getId ()); TeacherOptional = TeacherErrepository.findbyId (lehrer.getId ()); AsSertions.AsSertThat (lernoptional.get ()). Isnotnull (); AsSerions.assertHat (lernoptional.get (). GetKlass (). GetId ()). Isequalto (klass.getId ()); logger.info ("Suchen Sie nach Lehrerliste, keine Ausnahme. Gehen Sie zu, dass in der Lehrereinheit ein gelöschter KLASS -Entitätsaufzeichnung vorliegt." LIST <Arter> lehrerlist = (List <Arturer>) lehreErrepository.findall (); für (Lehrerlehrer1: Lehrerliste) {AsSerions.asserthat (lehre1.getklass (). getId ()). isequalto (klass.getId ()); } logger.info ("Löschen Sie den zugehörigen Klasstest und schauen Sie dann die Lehrereinheit nach, behaupten Sie, dass der gelöschte Klasstest gefunden wurde"); klastestrepository.deletebyId (klasstest.getId ()); TeacherOptional = TeacherErrepository.findbyId (lehrer.getId ()); AsSertions.AsSertThat (lernoptional.get ()). Isnotnull (); AsSerions.asserThat (lernoptional.get (). Getklasstest (). GetId ()). Isequalto (klasstest.getId ()); logger.info ("Sehen Sie sich die Lehrerliste erneut an, behaupten Sie, dass eine jpaObjectretRevievalFailureException auftreten wird (EntityNotFound -Ausnahme, eingekapselt und ausgeworfen) Ausnahme"); Boolean catchException = false; try {lehreErrepository.findall (); } catch (jpaObjectretRevievalFailureException e) {catchException = true; } Assertions.asserthat (catchException) .ISTRUE (); }} Zusammenfassen
Bei der Verwendung der Standardanschlag @SQLDELETETE und @WO können JPA -Daten die methode findById () gut verarbeiten, aber es kann die findAll () -Methode gut verarbeiten. Hier haben wir die Methode zur Umschreibung der CrunRepository -Methode implementiert. Wenn wir grundlegende Abfragen durchführen, verwenden wir unsere angepasste Methode, um deleted = true hinzuzufügen. Wenn JPA eine Assoziationsabfrage durchführt, da wir die @where -Annotation nicht festlegen, werden alle Daten abgefragt, wodurch die Ausnahme vermieden wird, die manchmal auftritt, wenn die Foundall () -frage ausgeführt wird.
In diesem Artikel geben wir nur einen Beispielcode an.
Wenn Sie den vollständigen Code benötigen, klicken Sie bitte auf: https://github.com/mengyunzhi/springbootSsamplecode/tree/master/softdelete.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.