Warum müssen wir die Annotation @Modifying für Abfragen in Data Jpa verwenden

Lesezeit: 5 Minuten

Zum Beispiel habe ich eine Methode in meiner CRUD-Schnittstelle, die einen Benutzer aus der Datenbank löscht:

public interface CrudUserRepository extends JpaRepository<User, Integer> {

    @Transactional
    @Modifying
    @Query("DELETE FROM User u WHERE u.id=:id")
    int delete(@Param("id") int id, @Param("userId") int userId);
}

Diese Methode funktioniert nur mit der Annotation @Modifying. Aber wozu braucht man hier die Anmerkung? Warum kann ich die Abfrage nicht analysieren und verstehen, dass es sich um eine modifizierende Abfrage handelt?

  • @Transactional-Annotation im Repository ist eine schlechte Praxis, verwenden Sie sie besser in Ihrem Service. Ursache Eine Geschäftsaktion (als Transaktion gekennzeichnet) kann aus mehreren Anforderungen an DB bestehen. sogar von mehreren DAO. Mehr hier: stackoverflow.com/questions/1079114/…

    – Dan Brandt

    11. September 2018 um 13:00 Uhr


  • @DanBrandt, es sei denn, Sie haben eine benutzerdefinierte Repo-Implementierung mit einer benutzerdefinierten Methode, die mehrere Abfragen als eine Transaktion ausführen muss (z. B. alle Datensätze zählen, 10 IDs auswählen, Datensätze nach ID auswählen, alle diese Daten in 1 Objekt zurückgeben).

    – Bojan Vukasovic

    10. Juli 2019 um 14:10 Uhr

Benutzer-Avatar
Youans

VORSICHT!

Verwenden @Modifying(clearAutomatically=true) löscht alle ausstehenden Updates für die verwalteten Entitäten im Persistenzkontext spring sagt Folgendes:

Dadurch wird die an die Methode kommentierte Abfrage als Aktualisierungsabfrage anstelle einer Auswahlabfrage ausgelöst. Da der EntityManager nach der Ausführung der Änderungsabfrage möglicherweise veraltete Entitäten enthält, löschen wir ihn nicht automatisch (siehe JavaDoc von EntityManager.clear() für Details), da dies effektiv alle nicht geleerten Änderungen verwirft, die noch im EntityManager ausstehen. Wenn Sie möchten, dass der EntityManager automatisch gelöscht wird, können Sie das Attribut clearAutomatically der Annotation @Modifying auf true setzen.

Glücklicherweise ab Spring Boot 2.0.4.RELEASE Spring Data hinzugefügt flushAutomatically Flagge (https://jira.spring.io/browse/DATAJPA-806), um alle verwalteten Entitäten im Persistenzkontext automatisch zu leeren Vor Ausführen der modifizierenden Abfrageprüfungsreferenz https://docs.spring.io/spring-data/jpa/docs/2.0.4.RELEASE/api/org/springframework/data/jpa/repository/Modifying.html#flushAutomatically

Also die sicherste Art zu verwenden @Modifying ist :

@Modifying(clearAutomatically=true, flushAutomatically=true)

Was passiert, wenn wir diese beiden Flags nicht verwenden??

Betrachten Sie den folgenden Code:

repo {
   @Modifying
   @Query("delete User u where u.active=0")
   public void deleteInActiveUsers();

}

Szenario 1 warum flushAutomatically

 service {
        User johnUser = userRepo.findById(1); // store in first level cache
        johnUser.setActive(false);
        repo.save(johnUser);

        repo.deleteInActiveUsers();// BAM it won't delete JOHN
        
        // JOHN still exist since john with active being false was not 
        // flushed into the database when @Modifying kicks in
    }

Szenario 2 warum clearAutomatically
Betrachten Sie im Folgenden, dass johnUser.active bereits falsch ist

service {
       User johnUser = userRepo.findById(1); // store in first level cache
       repo.deleteInActiveUsers(); // you think that john is deleted now 
       System.out.println(userRepo.findById(1).isPresent()) // TRUE!!!
       System.out.println(userRepo.count()) // 1 !!!
       
       // JOHN still exist since in this transaction persistence context
       // John's object was not cleared upon @Modifying query execution, 
       // John's object will still be fetched from 1st level cache 
       // `clearAutomatically` takes care of doing the 
       // clear part on the objects being modified for current 
       // transaction persistence context
}

Wenn Sie also – in derselben Transaktion – vor oder nach der Zeile, die dies tut, mit modifizierten Objekten spielen @Modifyingdann benutze clearAutomatically & flushAutomatically Wenn nicht, können Sie diese Flags überspringen

Übrigens ist dies ein weiterer Grund, warum Sie immer setzen sollten @Transactional Anmerkung auf Dienstebene, sodass Sie nur einen Persistenzkontext für alle Ihre verwalteten Entitäten in derselben Transaktion haben können. Da der Persistenzkontext an die Ruhezustandssitzung gebunden ist, müssen Sie wissen, dass eine Sitzung einige Transaktionen enthalten kann. Weitere Informationen finden Sie in dieser Antwort https://stackoverflow.com/a/5409180/1460591 Transaktionen zusammen (auch bekannt als Transaktionsisolation) in einer Transaktion (Standardisolation (erforderlich)) Weitere Informationen finden Sie in dieser Antwort https://stackoverflow.com/a/25710391/1460591

Um Dinge miteinander zu verbinden, wenn Sie mehrere Transaktionen haben (z. B. keine Transaktionsanmerkung im Dienst), haben Sie daher mehrere Sitzungen, wenn Sie der Funktionsweise von Spring Data folgen. Daher haben Sie mehrere Persistenzkontexte, was bedeutet, dass Sie ein Element in einer Persistenz löschen / ändern können Kontext auch bei der Verwendung flushAutomatically Das gleiche gelöschte/geänderte Element könnte abgerufen und im Persistenzkontext einer anderen Transaktion zwischengespeichert werden, was aufgrund falscher oder nicht synchronisierter Daten zu falschen Geschäftsentscheidungen führen würde

Dadurch wird die mit der Methode kommentierte Abfrage als Aktualisierungsabfrage anstelle einer Auswahl ausgelöst. Da der EntityManager nach der Ausführung der modifizierenden Abfrage möglicherweise veraltete Entitäten enthält, löschen wir ihn automatisch (siehe JavaDoc von EntityManager.clear() für Details). Dadurch werden alle nicht geleerten Änderungen, die noch im EntityManager ausstehen, effektiv gelöscht. Wenn Sie nicht möchten, dass der EntityManager automatisch gelöscht wird, können Sie das clearAutomatically-Attribut der @Modifying-Anmerkung auf false setzen;

Für weitere Details können Sie diesem Link folgen:-

http://docs.spring.io/spring-data/jpa/docs/1.3.4.RELEASE/reference/html/jpa.repositories.html

  • In der neueren JPA-Version sind beide Flags clearAutomatically und flushAutomatically standardmäßig auf false gesetzt. Wenn Sie also löschen oder leeren möchten, muss das Flag auf true gesetzt werden.

    – nur ich

    4. März 2019 um 14:12 Uhr

  • @justMe Wollen Sie damit sagen, dass in neueren Versionen, wenn wir nur die Annotation ohne Eigenschaften wie bündig oder klar ändern, diese Annotation nutzlos ist und nichts bewirkt?

    – der Programmierer

    4. Juli 2021 um 0:39 Uhr

  • @theprogrammer alles, was ich sage, sind diese Flags, die standardmäßig auf “false” gesetzt sind docs.spring.io/spring-data/jpa/docs/current/api/org/…, was passiert, wenn Sie sie nicht festlegen? Siehe die Antwort von Younas unten. oder offizielles Dokument docs.spring.io/spring-data/jpa/docs/current/reference/html/…

    – nur ich

    5. Juli 2021 um 6:56 Uhr

Abfragen, die a erfordern @Modifying Anmerkung umfassen INSERT-, UPDATE-, DELETE- und DDL-Anweisungen.

Hinzufügen @Modifying Anmerkung gibt an, dass die Abfrage nicht für eine SELECT-Abfrage bestimmt ist.

1159330cookie-checkWarum müssen wir die Annotation @Modifying für Abfragen in Data Jpa verwenden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy