[JAVA] So steuern Sie Transaktionen in Spring Boot ohne Verwendung von @Transactional

Oh, heute ist Heiligabend ~: santa :: snowflake: Machen Sie sich darüber keine Sorgen ... Dieses Mal zeige ich Ihnen, wie Sie Transaktionen in Spring Boot steuern können, ohne "@ Transactional" (annotationsgesteuertes Transaktionsmanagement) zu verwenden.

Einige Leute denken vielleicht, dass Sie "@ Transactional" verwenden sollten, aber da Sie "@ Transaction" nur für die von Ihnen erstellten Komponenten angeben können, hängt die OSS-Bibliothek des Drittanbieters nicht von Spring ab. Es ist nicht möglich, eine Transaktion auf eine Methode wie (offensichtlich ...: heat_smile :) anzuwenden.

Was soll ich machen?

Zusätzlich zu der Methode zur Verwendung von Anmerkungen zur Angabe der im Frühjahr zu handelnden Methode

Methoden etc. werden unterstützt.

Wenn Sie Spring schon lange verwenden, wurde in der Bean-Definition mit XML möglicherweise die folgende Transaktionssteuerungsdeklaration angezeigt. In diesem Beispiel unterliegen alle öffentlichen Methoden der Klasse "TxDemoApplication" der Transaktionssteuerung.

src/resources/transactionContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="
	   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
	   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">

	<tx:advice id="transactionAdvisor">
		<tx:attributes>
			<tx:method name="*" />
		</tx:attributes>
	</tx:advice>

	<aop:config>
		<aop:pointcut id="txDemoApplicationPointcut" expression="execution(* com.example.TxDemoApplication.*(..))"/>
		<aop:advisor advice-ref="transactionAdvisor" pointcut-ref="txDemoApplicationPointcut"/>
	</aop:config>

</beans>

Selbst beim Spring Boot funktioniert es, wenn Sie eine XML-Datei wie ↑ erstellen und wie unten gezeigt mit @ ImportResource laden.

@SpringBootApplication
@ImportResource("classpath:/transactionContext.xml")
public class TxDemoApplication implements CommandLineRunner {
    // ...
}

Aber ... ich möchte nicht mehr zur XML-Datei zurückkehren ...: heat_smile: Wenn Sie Spring from Spring Boot verwenden (diejenigen, die nur Java Config kennen), frage ich mich, wie man Beans mit XML ~ definiert Daher gibt es einige Leute: zwinker:

Machen Sie dasselbe mit Java Config! !!

Wenn Sie dasselbe mit Java Config ausdrücken möchten ... Erstellen Sie einfach die folgende Java Config.

@Configuration
public class TransactionConfig {
	@Bean
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			PlatformTransactionManager transactionManager) {

		//Geben Sie die Methode zum Verwalten von Transaktionen und die für die Transaktionssteuerung erforderlichen Attributwerte an.
		MethodMapTransactionAttributeSource source = new MethodMapTransactionAttributeSource();
		source.addTransactionalMethod(TxDemoApplication.class, "*", new RuleBasedTransactionAttribute());

		//Generieren Sie einen AOP Advisor, der Transaktionen steuert
		//Beratung zur Transaktionskontrolle(TransactionInteceptor)Der Punktschnitt, der den Anwendungsort von angibt, ist mit der in ↑ angegebenen Methode verknüpft.
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(source);
		advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
		return advisor;
	}

}

Note:

Wenn Sie diesen Mechanismus verwenden möchten, benötigen Sie die JAR von "org.aspectj: aspectjweaver" im Klassenpfad. Fügen Sie also "org.springframework.boot: spring-boot-Starter-aop" als abhängige Bibliothek hinzu. ..

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Warning:

Mit Spring Boot ermöglicht der automatische Konfigurationsmechanismus auch die Steuerung von Transaktionen mithilfe von "@ Transactional" (annotationsgesteuertes Transaktionsmanagement). Daher ... Wenn der in Java Config in ↑ angegebenen Methode "@ Transactional" hinzugefügt wird, wird der Hinweis ("TransactionInteceptor") zur Transaktionssteuerung zweimal angewendet. Seien Sie also vorsichtig.

TransactionAttributeSource-Typ

Im obigen Beispiel wird "MethodMapTransactionAttributeSource" verwendet, Spring bietet jedoch einige Implementierungsklassen für "TransactionAttributeSource".

Name der Klasse Erläuterung
NameMatchTransactionAttributeSource Wenden Sie die Transaktionssteuerung auf Methoden an, die dem angegebenen Methodennamen (Muster) entsprechen.
MethodMapTransactionAttributeSource Wenden Sie die Transaktionssteuerung auf den angegebenen Methodennamen (Muster) der angegebenen Klasse an
MatchAlwaysTransactionAttributeSource Wenden Sie die Transaktionssteuerung auf alle Methoden an
AnnotationTransactionAttributeSource Wenden Sie die Transaktionssteuerung auf mit Spring, JTA und EJB kommentierte Klassenmethoden an (diese Klasse wird bei der automatischen Konfiguration von Spring Boot verwendet).
CompositeTransactionAttributeSource Plural-TransactionAttributeSourceTransaktionssteuerung aggregieren und anwenden

Filter für zutreffende Klassen

Mit BeanFactoryTransactionAttributeSourceAdvisor können Sie die Klassen filtern, für die AOP gilt. Beispiel: Wenn Sie nur Beans anwenden möchten, denen "@ Service" zugewiesen ist, können Sie die folgenden Beans definieren.

@Configuration
public class TransactionConfig {
	@Bean
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			PlatformTransactionManager transactionManager) {

		NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
		source.addTransactionalMethod("*", new RuleBasedTransactionAttribute());

		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(source);
		advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
		advisor.setClassFilter(clazz -> AnnotationUtils.findAnnotation(clazz, Service.class) != null); //Implementieren Sie Filterbedingungen und`setClassFilter`Anruf
		return advisor;
	}

}

Verifizierungs-App

Unten finden Sie eine Beispielanwendung, die zur Überprüfung des Betriebs erstellt wurde.

Überprüfungsumgebung

Ein Projekt erstellen

Laden Sie das Projekt herunter, indem Sie "JDBC", "H2" und "AOP" als abhängige Bibliotheken für "SPRING INITIALIZR" auswählen.

Protokollstufe ändern

Stellen Sie den Spring JDBC-Protokollausgabemodus auf Debuggen ein, um festzustellen, ob die Transaktion angewendet wurde.

src/resources/application.properties


logging.level.org.springframework.jdbc=debug

Erstellen einer App und Definieren von Bnea

Implementieren Sie als Nächstes "CommandRunner" in der Spring Boot-Anwendung und definieren Sie die Bean für die Transaktionssteuerung.

package com.example;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;
import org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

@SpringBootApplication
public class TxDemoApplication implements CommandLineRunner {

	public static void main(String[] args) {
		SpringApplication.run(TxDemoApplication.class, args);
	}

	private final JdbcOperations jdbcOperations;

	public TxDemoApplication(JdbcOperations jdbcOperations) {
		this.jdbcOperations = jdbcOperations;
	}

	@Override //Diese Methode unterliegt der Transaktionskontrolle, aber ...@Transaktion wird nicht gewährt! !!
	public void run(String... args) throws Exception {
		Integer value = jdbcOperations.queryForObject("SELECT 1", Integer.class);
		System.out.println(value);
	}

	@Configuration
	static class TransactionConfig {
		@Bean
		public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
				PlatformTransactionManager transactionManager) {

			MethodMapTransactionAttributeSource source = new MethodMapTransactionAttributeSource();
			source.addTransactionalMethod(TxDemoApplication.class, "*", new RuleBasedTransactionAttribute());

			BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
			advisor.setTransactionAttributeSource(source);
			advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
			return advisor;
		}

	}

}

Führen Sie die App aus

Lassen Sie uns nun die Spring Boot-Anwendung ausführen.

$ ./mvnw spring-boot:run
...

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.3.RELEASE)

2016-12-24 16:20:30.713  INFO 58327 --- [           main] com.example.TxDemoApplication            : Starting TxDemoApplication on Kazuki-no-MacBook-Pro.local with PID 58327 (/Users/shimizukazuki/Downloads/tx-demo/target/classes started by shimizukazuki in /Users/shimizukazuki/Downloads/tx-demo)
2016-12-24 16:20:30.715  INFO 58327 --- [           main] com.example.TxDemoApplication            : No active profile set, falling back to default profiles: default
2016-12-24 16:20:30.748  INFO 58327 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1e2e2b3: startup date [Sat Dec 24 16:20:30 JST 2016]; root of context hierarchy
2016-12-24 16:20:31.454  INFO 58327 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-12-24 16:20:31.469 DEBUG 58327 --- [           main] o.s.j.d.DataSourceTransactionManager     : Creating new transaction with name [com.example.TxDemoApplication$$EnhancerBySpringCGLIB$$9f83f17d.run]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2016-12-24 16:20:31.609 DEBUG 58327 --- [           main] o.s.j.d.DataSourceTransactionManager     : Acquired Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]] for JDBC transaction
2016-12-24 16:20:31.611 DEBUG 58327 --- [           main] o.s.j.d.DataSourceTransactionManager     : Switching JDBC Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]] to manual commit
2016-12-24 16:20:31.618 DEBUG 58327 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL query [SELECT 1]
1
2016-12-24 16:20:31.638 DEBUG 58327 --- [           main] o.s.j.d.DataSourceTransactionManager     : Initiating transaction commit
2016-12-24 16:20:31.638 DEBUG 58327 --- [           main] o.s.j.d.DataSourceTransactionManager     : Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]]
2016-12-24 16:20:31.639 DEBUG 58327 --- [           main] o.s.j.d.DataSourceTransactionManager     : Releasing JDBC Connection [ProxyConnection[PooledConnection[conn9: url=jdbc:h2:mem:testdb user=SA]]] after transaction
2016-12-24 16:20:31.639 DEBUG 58327 --- [           main] o.s.jdbc.datasource.DataSourceUtils      : Returning JDBC Connection to DataSource
2016-12-24 16:20:31.642  INFO 58327 --- [           main] com.example.TxDemoApplication            : Started TxDemoApplication in 1.106 seconds (JVM running for 3.466)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.612 s
[INFO] Finished at: 2016-12-24T16:20:31+09:00
[INFO] Final Memory: 24M/315M
[INFO] ------------------------------------------------------------------------
2016-12-24 16:20:31.742  INFO 58327 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@1e2e2b3: startup date [Sat Dec 24 16:20:30 JST 2016]; root of context hierarchy
2016-12-24 16:20:31.744  INFO 58327 --- [       Thread-1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

Wenn Sie sich das Konsolenprotokoll ansehen, sehen Sie, dass die Transaktion vor und nach der Implementierung von SQL gestartet, festgeschrieben und beendet wird: clap :: clap :: clap:

Zusammenfassung

Es wird möglicherweise nicht oft verwendet, aber ... Sie können Transaktionen für Methoden steuern, die nicht über "@ Transactional" verfügen. Grundsätzlich denke ich, dass es besser ist, "@ Transactional" hinzuzufügen, um Transaktionen für die von Ihnen erstellten Komponenten zu steuern. Abhängig von den Anforderungen der Anwendung kann die diesmal eingeführte Methode in einigen Fällen jedoch effektiv sein. Hmm.

schließlich

Happy Christmas 2016 !! :wave:

Recommended Posts

So steuern Sie Transaktionen in Spring Boot ohne Verwendung von @Transactional
So fügen Sie in Spring Boot einen Klassenpfad hinzu
So binden Sie mit einer Eigenschaftendatei in Spring Boot
So erstellen Sie ein Spring Boot-Projekt in IntelliJ
Verwendung von CommandLineRunner im Spring Batch von Spring Boot
Testen Sie die Klasse mit Feldinjektion im Spring-Boot-Test, ohne den Spring-Container zu verwenden
Wie man Lombok im Frühling benutzt
So ändern Sie den Einstellungswert von application.properties beim Booten im Frühjahrsstart
Stellen Sie Spring Boot-Anwendungen für Heroku bereit, ohne die Heroku-CLI zu verwenden
So stellen Sie Spring Boot + PostgreSQL ein
Aufrufen und Verwenden der API in Java (Spring Boot)
Verwendung von ModelMapper (Spring Boot)
So erstellen Sie mit SPRING INITIALIZR einen Hinadan für ein Spring Boot-Projekt
Hochladen und Herunterladen von Dateien mit Ajax mit Spring Boot (ohne JQuery)
Wie kann ich Spring Tool in Eclipse 4.6.3 einbinden?
Verwendung von MyBatis2 (iBatis) mit Spring Boot 1.4 (Spring 4)
Verwendung des eingebauten h2db mit Federstiefel
So verkleinern Sie das Spring Boot Docker-Image
Verwendung von Spring Boot-Sitzungsattributen (@SessionAttributes)
Wenden Sie Twitter Bootstrap 4 mithilfe von Webjars auf Spring Boot 2 an
So definieren Sie mehrere orm.xml in Spring4, JPA2.1
[Spring Boot] So verweisen Sie auf die Eigenschaftendatei
Spring Boot - So stellen Sie das Sitzungszeitlimit ein
Wenn Sie irgendwo einen Fehler melden möchten, wenn Sie graphql-spring-boot mit Spring Boot verwenden
So legen Sie Umgebungsvariablen in der Eigenschaftendatei der Spring-Boot-Anwendung fest
So stellen Sie Spring Boot Dependency Injection (DI) ein
So senden Sie einen Wert in HTML ohne Bildschirmübergang
So schreiben Sie einen Komponententest für Spring Boot 2
[Spring Boot] So erstellen Sie ein Projekt (für Anfänger)
[Einführung in Spring Boot] Senden Sie ein Formular mit thymeleaf
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
So starten Sie den lokalen Server von Tomcat ohne Eclipse
Führen Sie swagger-ui in die in Spring Boot implementierte REST-API ein
Booten nach Umgebung mit Spring Boot of Maven
Verwendung des In-Memory-Job-Repositorys mit Spring Batch
So implementieren Sie den Authentifizierungsprozess durch Angabe von Benutzername und Kennwort in Spring Boot
Legen Sie den Kontextparameter in Spring Boot fest
Versuchen Sie Spring Boot von 0 bis 100.
So übergeben Sie ein Objekt in MyBatis an Mapper, ohne ein Argument durchzugehen
Spring Boot 2 Multiprojekt mit Gradle
Verwendung derselben Mapper-Klasse in mehreren Datenquellen mit Spring Boot + MyBatis
Verhindern Sie Vorgänge! Sichere manuelle Datenaktualisierungsmethode für Rails mithilfe von Transaktionen
So entwickeln Sie in Xib-Dateien ohne Verwendung von Storyboard
Einführung in Spring Boot ~ ~ DI ~
So stellen Sie jQuery in Rails-Apps mit Webpacker bereit
So geben Sie Array-Werte ohne Verwendung einer for-Anweisung aus
So installieren Sie JDK 8 unter Windows ohne Verwendung des Installationsprogramms
Verwenden Sie thymeleaf3 mit parent, ohne Spring-Boot-Starter-Parent in Spring Boot anzugeben
Wichtige Änderungen in Spring Boot 1.5
NoHttpResponseException in Spring Boot + WireMock
So verbinden Sie eine Tabelle ohne DBFlute und SQL
Einführung in Spring Boot Teil 1
Versuchen Sie es mit Spring Boot Security
Ich habe versucht, mit Swagger mit Spring Boot zu beginnen
8 Dinge, die mit Spring Boot und JPA in die DB eingefügt werden müssen
Lassen Sie uns herausfinden, wie Sie mit Request Body mit der REST-API von Spring Boot empfangen können
Verwenden Sie im Spring Boot @ControllerAdvice, @ExceptionHandler, HandlerExceptionResolver, um Ausnahmen abzufangen
So autorisieren Sie mit graphql-ruby
[Sprint Boot] Verwendung der drei in org.springframework.jdbc.core.namedparam definierten Arten von SqlParameterSource