Wie verwende ich @Transactional mit Spring Data?

82

Ich habe gerade angefangen, an einem Spring-Data-, Hibernate-, MySQL- und JPA-Projekt zu arbeiten. Ich habe auf Spring-Data umgestellt, damit ich mich nicht darum kümmern muss, Abfragen von Hand zu erstellen.

Ich habe festgestellt, dass die Verwendung von @Transactionalnicht erforderlich ist, wenn Sie Spring-Daten verwenden, da ich meine Abfragen auch ohne die Anmerkung ausprobiert habe.

Gibt es einen bestimmten Grund, warum ich die @TransactionalAnmerkung verwenden sollte / nicht verwenden sollte ?

Werke:

@Transactional
public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

Funktioniert auch:

public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

Danke im Voraus!

Byron Voorbach
quelle

Antworten:

140

Worum geht es in Ihrer Frage eigentlich? Die Verwendung der @RepositoryAnmerkung oder @Transactional.

@Repositorywird überhaupt nicht benötigt, da die von Ihnen deklarierte Schnittstelle von einem Proxy unterstützt wird, für den die Spring Data-Infrastruktur eine Ausnahmeübersetzung erstellt und aktiviert. Die Verwendung dieser Anmerkung auf einer Spring Data-Repository-Schnittstelle hat also keinerlei Auswirkungen.

@Transactional- Für das JPA-Modul haben wir diese Anmerkung in der Implementierungsklasse, die den Proxy ( SimpleJpaRepository) unterstützt. Dies hat zwei Gründe: Erstens erfordert das Fortbestehen und Löschen von Objekten eine Transaktion in JPA. Daher müssen wir sicherstellen, dass eine Transaktion ausgeführt wird, indem wir die Methode mit Anmerkungen versehen @Transactional.

Lesemethoden wie findAll()und findOne(…)verwenden , @Transactional(readOnly = true)die nicht unbedingt erforderlich ist , sondern löst ein paar Optimierungen in der Transaktion Infrastruktur (Einstellung der lassen Persistenz - Provider möglicherweise verschmutzt Prüfungen nicht durchgeführt , wenn das Schließen ). Darüber hinaus wird das Flag auch für die JDBC-Verbindung gesetzt, was zu weiteren Optimierungen auf dieser Ebene führt.FlushModeMANUALEntityManager

Je nachdem, welche Datenbank Sie verwenden, können Tabellensperren weggelassen oder sogar Schreibvorgänge abgelehnt werden, die Sie möglicherweise versehentlich auslösen. Daher empfehlen wir, auch @Transactional(readOnly = true)Abfragemethoden zu verwenden, mit denen Sie diese Anmerkung problemlos zu Ihrer Repository-Schnittstelle hinzufügen können. Stellen Sie sicher, dass Sie @Transactionalden Manipulationsmethoden, die Sie möglicherweise in dieser Schnittstelle deklariert oder neu dekoriert haben , eine Ebene hinzufügen .

Oliver Drotbohm
quelle
8
Kurz gesagt: Ich sollte @Transactional für das Hinzufügen / Bearbeiten / Löschen von Abfragen und @Transaction (readOnly = true) für ausgewählte Abfragen bei allen meinen DAO-Methoden verwenden.
Byron Voorbach
20
Genau. Der einfachste Weg, dies zu tun, besteht darin, @Transactional(readOnly = true)die Schnittstelle zu verwenden (da sie normalerweise hauptsächlich Finder-Methoden enthält) und diese Einstellung für jede modifizierende Abfragemethode mit einer Ebene zu überschreiben @Transactional. So wird es eigentlich gemacht SimpleJpaRepositoy.
Oliver Drotbohm
@Oliver, danke für die umfassende Erklärung. Aber während Sie einen anderen Link durchgehen [Transaction-Pit-Falls] < ibm.com/developerworks/java/library/j-ts1/index.html#listing8 >. Es heißt " Unterm Strich ist , dass , wenn Sie ein ORM-basiertes Framework verwenden, das Nur - Lese-Flag ziemlich nutzlos ist und in den meisten Fällen ignoriert. Wenn Sie aber nach wie vor auf der Verwendung darauf bestehen, immer den Ausbreitungsmodus zu den Auflagern gesetzt . Nachdem ich dies gelesen habe, bin ich mir nicht sicher, ob ich (readOnly = true) alleine verwenden soll. Sollte es immer mit dem Ausbreitungsmodus als UNTERSTÜTZUNG verwendet werden.
Anupam Gupta
8
Fast alles ist in diesem Abschnitt des Artikels falsch. Indem Sie angeben, dass Sie nicht schreiben, kann (wird) die JDBC-gesteuerte Leistung die Leistung für DB-Interaktionen verbessern. Es kann auch versehentlich ausgegebene Schreibvorgänge erkennen und ablehnen. Darüber hinaus deaktiviert Spring das JPA / Hibernate-Flushing im schreibgeschützten Modus, was die Leistung erheblich beeinträchtigen kann, wenn Sie große Objektdiagramme lesen, da der Anbieter dann keine schmutzigen Überprüfungen durchführen muss. Die Flagge hat zwar keinen großen Einfluss auf die Transaktion selbst, aber das ist bei weitem nicht alles, was zu beachten ist.
Oliver Drotbohm
Ich kann für die Leistungsverbesserungen bei großen Objektdiagrammen oder Anwendungsfällen beim Laden einer großen Anzahl verwalteter Objekte bürgen.
Shailendra
3

Ich denke, dass die Frage etwas weiter gefasst ist und nicht auf die Anmerkungen auf der Datenzugriffsschicht reduziert werden kann. Wir müssen den gesamten Stapel der Anwendung, die Transaktionsstrategien, die wir anwenden möchten, usw. berücksichtigen. Es gibt eine sehr umfassende Reihe von Artikeln zu diesem Thema von Mark Richards auf der IBM Developerworks-Website. Den ersten finden Sie hier: https://developer.ibm.com/articles/j-ts1/

Freundliche Grüße

dgiffone
quelle
2

Sie sollten @RepositoryAnmerkungen verwenden

Dies liegt daran @Repository, dass Sie Ihre ungeprüfte SQL-Ausnahme in Spring Excpetion übersetzen. Die einzige Ausnahme, die Sie behandeln sollten, istDataAccessException

danny.lesnik
quelle
10
Dies gilt im Allgemeinen für die Verwendung von Spring. Da Spring Data-Repositorys jedoch bereits von einem Spring-Proxy unterstützt werden, macht die Verwendung von @Repository keinen Unterschied.
Aleksander Blomskøld
0

Wir verwenden auch die @ Transactional-Annotation, um den Datensatz zu sperren, damit ein anderer Thread / eine andere Anforderung den Lesevorgang nicht ändert.

Zozo
quelle