Transaktionen mit Spring und JPA
1. Überblick
In diesem Tutorial werdenthe right way to configure Spring Transactions, die Verwendung der Annotation@Transactional und allgemeine Fallstricke erläutert.
Weitere Informationen zur Konfiguration der Kernpersistenz finden Sie inSpring with JPA tutorial.
Grundsätzlich gibt es zwei verschiedene Möglichkeiten, um Transaktionen zu konfigurieren: Anmerkungen und AOP - jede mit ihren eigenen Vorteilen. Wir werden hier die häufigere Annotation-Konfiguration diskutieren.
Weitere Lektüre:
Separate Spring DataSource für Tests konfigurieren
Ein schnelles, praktisches Tutorial zum Konfigurieren einer separaten Datenquelle zum Testen in einer Spring-Anwendung.
Kurzanleitung zum Laden von Anfangsdaten mit Spring Boot
Ein schnelles und praktisches Beispiel für die Verwendung von data.sql- und schema.sql-Dateien in Spring Boot.
Ruhezustand / JPA-SQL-Anweisungen von Spring Boot anzeigen
Erfahren Sie, wie Sie die Protokollierung der generierten SQL-Anweisungen in Ihrer Spring Boot-Anwendung konfigurieren können.
2. Konfigurieren Sie Transaktionen ohne XML
In Spring 3.1 werdenthe @EnableTransactionManagement annotation eingeführt, die wir in einer@Configuration-Klasse verwenden und die Transaktionsunterstützung aktivieren können:
@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{
@Bean
public LocalContainerEntityManagerFactoryBean
entityManagerFactoryBean(){
//...
}
@Bean
public PlatformTransactionManager transactionManager(){
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
entityManagerFactoryBean().getObject() );
return transactionManager;
}
}
Wenn wir jedoch ein Spring Boot-Projekt verwenden und Spring-Data- * oder Spring-TX-Abhängigkeiten vom Klassenpfad haben, ist die Transaktionsverwaltung standardmäßig aktiviert.
3. Konfigurieren Sie Transaktionen mit XML
Vor 3.1 oder wenn Java keine Option ist, finden Sie hier die XML-Konfiguration unter Verwendung vonannotation-driven und der Namespace-Unterstützung:
4. Die Annotation@Transactional
Mit konfigurierten Transaktionen können wir jetzt eine Bean mit@Transactional entweder auf Klassen- oder Methodenebene mit Anmerkungen versehen:
@Service
@Transactional
public class FooService {
//...
}
Die Annotation unterstützt auchfurther configuration:
-
diePropagation Type der Transaktion
-
dieIsolation Level der Transaktion
-
aTimeout für die von der Transaktion umschlossene Operation
-
areadOnly flag - ein Hinweis für den Persistenzanbieter, dass die Transaktion schreibgeschützt sein sollte
-
dieRollback Regeln für die Transaktion
Beachten Sie, dass das Rollback standardmäßig nur zur Laufzeit ausgeführt wird (nicht aktivierte Ausnahmen). The checked exception does not trigger a rollback der Transaktion. Wir können dieses Verhalten natürlich mit den AnnotationsparameternrollbackFor undnoRollbackFor konfigurieren.
5. Möglichen Gefahren
5.1. Transaktionen und Proxies
Auf einem hohen NiveauSpring creates proxies for all the classes annotated with @Transactional - entweder für die Klasse oder für eine der Methoden. Der Proxy ermöglicht es dem Framework, Transaktionslogik vor und nach der ausgeführten Methode einzufügen - hauptsächlich zum Starten und Festschreiben der Transaktion.
Es ist wichtig zu beachten, dass der Proxy standardmäßig ein Java Dynamic Proxy ist, wenn die Transaktions-Bean eine Schnittstelle implementiert. Dies bedeutet, dass nur externe Methodenaufrufe abgefangen werden, die über den Proxy eingehen. Any self-invocation calls will not start any transaction,, auch wenn die Methode die Annotation@Transactional enthält.
Eine weitere Einschränkung bei der Verwendung von Proxys besteht darin, dassonly public methods should be annotated with @Transactional. Methoden für andere Sichtbarkeiten die Anmerkung einfach stillschweigend ignorieren, da diese nicht als Proxys verwendet werden.
This article discusses further proxying pitfalls hier sehr detailliert.
5.2. Ändern der Isolationsstufe
Wir können auch die Transaktionsisolationsstufe ändern:
@Transactional(isolation = Isolation.SERIALIZABLE)
Beachten Sie, dass dies in Frühjahr 4.1 tatsächlichintroduced war. Wenn wir das obige Beispiel vor Spring 4.1 ausführen, führt dies zu:
org.springframework.transaction.InvalidIsolationLevelException: Standard-JPA unterstützt keine benutzerdefinierten Isolationsstufen. Verwenden Sie für Ihre JPA-Implementierung ein speziellesJpaDialect
5.3. Schreibgeschützte Transaktionen
Das FlagreadOnly erzeugt normalerweise Verwirrung, insbesondere bei der Arbeit mit JPA. aus dem Javadoc:
Dies dient nur als Hinweis für das eigentliche Transaktionssubsystem. not necessarily führt zu fehlgeschlagenen Schreibzugriffsversuchen. Ein Transaktionsmanager, der den schreibgeschützten Hinweis nicht interpretieren kann, löstnot eine Ausnahme aus, wenn er nach einer schreibgeschützten Transaktion gefragt wird.
Tatsache ist, dasswe can’t be sure that an insert or update will not occur when the readOnly flag is set. Dieses Verhalten ist herstellerabhängig, während JPA herstellerunabhängig ist.
Es ist auch wichtig zu verstehen, dassthe readOnly flag is only relevant inside a transaction. Wenn eine Operation außerhalb eines Transaktionskontexts ausgeführt wird, wird das Flag einfach ignoriert. Ein einfaches Beispiel hierfür würde eine mit folgenden Anmerkungen versehene Methode aufrufen:
@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )
aus einem nicht-transaktionalen Kontext - Eine Transaktion wird nicht erstellt und das FlagreadOnlywird ignoriert.
5.4. Transaktionsprotokollierung
Eine hilfreiche Methode, um transaktionsbezogene Probleme zu verstehen, ist die Feinabstimmung der Protokollierung in den Transaktionspaketen. Das relevante Paket im Frühjahr lautet „org.springframework.transaction”, which should be configured with a logging level of TRACE.
6. Fazit
Wir haben die grundlegende Konfiguration der Transaktionssemantik unter Verwendung von Java und XML, die Verwendung von@Transactional und Best Practices einer Transaktionsstrategie behandelt.
Wie immer ist der in diesem Artikel vorgestellte Codeover on Github verfügbar.