Transacties met Spring en JPA

1. Overzicht

Deze tutorial zal bespreken de juiste manier om Spring Transactions te configureren, hoe u de @Transactional annotatie en veelvoorkomende valkuilen.

Voor een meer diepgaande discussie over de kernpersistentieconfiguratie, bekijk de Spring with JPA-tutorial.

In principe zijn er twee verschillende manieren om transacties te configureren - annotaties en AOP - elk met hun eigen voordelen. We gaan de meer algemene annotatie-configuratie hier bespreken.

2. Configureer transacties

Spring 3.1 introduceert de @EnableTransactionManagement annotatie die we kunnen gebruiken in een @Configuratie class en schakel transactionele ondersteuning in:

@Configuration @EnableTransactionManagement openbare klasse PersistenceJPAConfig {@Bean openbaar LocalContainerEntityManagerFactoryBean entityManagerFactoryBean () {// ...} @Bean openbaar PlatformTransactionManager transactionManager () {JpaTransactionManager transactionManager = nieuwe JpaTransactionManager (); transactionManager.setEntityManagerFactory (entityManagerFactoryBean (). getObject ()); return transactionManager; }}

Echter, als we een Spring Boot-project gebruiken en een spring-data- * of spring-tx-afhankelijkheid hebben op het klassenpad, dan wordt transactiebeheer standaard ingeschakeld.

3. Configureer transacties met XML

Vóór 3.1 of als Java geen optie is, hier is de XML-configuratie met annotatiegestuurd en de naamruimte-ondersteuning:

4. Het @Transactional Annotatie

Met geconfigureerde transacties kunnen we nu een boon annoteren met @Transactional hetzij op klasse- of methode-niveau:

@Service @Transactional openbare klasse FooService {// ...}

De annotatie ondersteunt verdere configuratie ook:

  • de Voortplantingstype van de transactie
  • de Isolatieniveau van de transactie
  • een Time-out voor de operatie verpakt door de transactie
  • een readOnly vlag - een hint voor de persistentieprovider dat de transactie alleen moet worden gelezen
  • de Terugrollen regels voor de transactie

Merk op dat - standaard, rollback gebeurt voor runtime, alleen ongecontroleerde uitzonderingen. De aangevinkte uitzondering activeert geen rollback van de transactie. We kunnen dit gedrag natuurlijk configureren met de rollback voor en noRollbackFor annotatieparameters.

5. Mogelijke valkuilen

5.1. Transacties en volmachten

Op een hoog niveau, Spring creëert proxy's voor alle klassen met annotaties @Transactional - ofwel op de klasse of op een van de methoden. De proxy stelt het raamwerk in staat om transactionele logica voor en na de lopende methode te injecteren - voornamelijk voor het starten en vastleggen van de transactie.

Wat belangrijk is om in gedachten te houden, is dat als de transactional bean een interface implementeert, de proxy standaard een Java Dynamic Proxy is. Dit betekent dat alleen externe methodeaanroepen die via de proxy binnenkomen, worden onderschept. Elke zelfoproep zal geen enkele transactie starten, zelfs als de methode de @Transactional annotatie.

Een ander voorbehoud bij het gebruik van proxy's is dat alleen openbare methoden moeten worden geannoteerd met @Transactional. Methoden voor andere zichtbaarheid zullen de annotatie gewoon in stilte negeren, aangezien deze niet proxy zijn.

In dit artikel worden verdere valkuilen van proxy's hier in detail besproken.

5.2. Het isolatieniveau wijzigen

We kunnen ook het transactie-isolatieniveau wijzigen:

@Transactional (isolatie = Isolation.SERIALIZABLE)

Merk op dat dit feitelijk is geïntroduceerd in Spring 4.1; als we het bovenstaande voorbeeld uitvoeren vóór Spring 4.1, zal dit resulteren in:

org.springframework.transaction.InvalidIsolationLevelException: Standard JPA ondersteunt geen aangepaste isolatieniveaus - gebruik een special JpaDialect voor uw PPV-implementatie

5.3. Alleen-lezen transacties

De alleen lezen vlag veroorzaakt meestal verwarring, vooral wanneer u met JPA werkt; van de Javadoc:

Dit dient slechts als een hint voor het eigenlijke transactiesubsysteem; het zal niet noodzakelijk het mislukken van pogingen tot schrijftoegang veroorzaken. Een transactiebeheerder die de alleen-lezen hint niet kan interpreteren, zal dat wel doen niet gooi een uitzondering wanneer om een ​​alleen-lezen transactie wordt gevraagd.

Het feit is dat we kunnen er niet zeker van zijn dat er geen insert of update zal plaatsvinden wanneer het alleen lezen vlag is ingesteld. Dit gedrag is afhankelijk van de leverancier, terwijl JPA leverancieronafhankelijk is.

Het is ook belangrijk om dat te begrijpen de alleen lezen vlag is alleen relevant binnen een transactie. Als een bewerking plaatsvindt buiten een transactionele context, wordt de vlag eenvoudigweg genegeerd. Een eenvoudig voorbeeld hiervan zou een methode aanroepen die is geannoteerd met:

@Transactional (propagation = Propagation.SUPPORTS, readOnly = true)

vanuit een niet-transactionele context - er wordt geen transactie gemaakt en de alleen lezen vlag wordt genegeerd.

5.4. Transactieregistratie

Een handige methode om transactiegerelateerde problemen te begrijpen, is het verfijnen van de logboekregistratie in de transactiepakketten. Het relevante pakket in het voorjaar is “org.springframework.transaction ”, dat moet worden geconfigureerd met het logboekniveau TRACE.

6. Conclusie

We hebben de basisconfiguratie van transactionele semantiek behandeld met zowel Java als XML, hoe te gebruiken @Transactional en best practices van een transactiestrategie.

Zoals altijd is de code die in dit artikel wordt gepresenteerd, beschikbaar op Github.


$config[zx-auto] not found$config[zx-overlay] not found