Spring Transaction - Transaction Strategy

1. Traditional transaction strategy
Traditional transaction has two strategies, global transaction and local transaction.
Global transactions: Managed by an application server (such as WebLogic or JBoss), requiring JTA support from the underlying server.
Local transaction: It is related to the persistence technology used by the bottom layer. When using the JDBC persistence technology, you need to use the Connection object to operate the transaction; when using the Hibernate persistence technology, you need to use the Session object to operate the transaction.
Global transactions can span multiple transactional resources (typical examples are relational databases and message queues). With local transactions, the application server does not need to participate in transaction management, so the correctness of transactions across multiple transactional resources cannot be guaranteed. Of course, in practice most applications use a single transactional resource.
The following figure is a comparison of transaction operation codes of JTA global transaction, JDBC local transaction, and Hibernate transaction:

As can be seen from the figure, when traditional transaction programming strategy is adopted, program code must be coupled with specific transaction operation code. The consequence of this is that when the application needs to switch between different transaction strategies, the developer must manually modify the program code. When using the Spring transaction operation strategy, this situation can be changed.

2. Spring transaction strategy
Spring transaction strategy is embodied through PlatformTransactionManager interface, which is the core of Spring transaction strategy. The source code of this interface is as follows:
public interface PlatformTransactionManager
{
	//Platform independent method to get transaction
    public abstract TransactionStatus getTransaction(TransactionDefinition transactiondefinition)
        throws TransactionException;

	//Platform independent transaction commit method
    public abstract void commit(TransactionStatus transactionstatus)
        throws TransactionException;

	//Platform independent transaction rollback method
    public abstract void rollback(TransactionStatus transactionstatus)
        throws TransactionException;
}

PlatformTransactionManager is an interface separated from any transaction strategy. With the switching of different underlying transaction strategies, applications must adopt different implementation classes. PlatformTransactionManager is not bundled with any transaction resources, it can be applied to any transaction strategy, combined with Spring's IoC container, it can inject relevant platform features into PlatformTransactionManager.
PlatformTransactionManager has many different implementation classes, and the application program is oriented towards platform programming that has nothing to do with the interface. When the bottom layer adopts different persistence layer technologies, the system only needs to use different PlatformTransactionManager implementation classes - and this switching is usually done by the Spring container. Management, the application does not need to be coupled with a specific transaction API, nor with a specific implementation class, thus completely separating the application from the persistence technology and the transaction API.

Spring's specific transaction management is done by different implementation classes of PlatformTransactionManager. When configuring the PlatformTransactionManager Bean in the Spring container, different implementation classes must be provided for different environments.
1. The configuration file of the JDBC local transaction strategy is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	
	<!-- define data source bean -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	    <!-- Specify the driver to connect to the database -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<!-- Specify the URL to connect to the database -->
		<property name="url" value="jdbc:oracle:****" />
		<property name="username" value="****" />
		<property name="password" value="****" />
		<!-- Specify the maximum number of connections to connect to the database connection pool-->
		<property name="maxPoolSize" value="40" />
		<!-- Specify the maximum number of connections to connect to the database connection pool-->
		<property name="minPoolSize" value="1" />
		<!-- Specify the number of initial connections to connect to the database connection pool-->
		<property name="initialPoolSize" value="1" />
		<!-- Specify the maximum idle time for connections to the database connection pool -->
		<property name="maxIdleTime" value="20" />
	</bean>
	
	<!-- Configure the local transaction manager of the JDBC data source, using the DataSourceTransactionManager class -->
	<!-- This class implements the PlatformTransactionManager interface, which is a specific implementation for using a database connection -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- A reference to dataSource needs to be injected -->
		<property name="dataSource" ref="dataSource" />
	</bean>
<beans>


2. The configuration file of the container-managed JTA global transaction is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	
	<!-- Configure JNDI data source bean -->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
	    <!-- JNDI for container-managed data sources -->
		<property name="jndiName" value="jdbc/jpetstore" />
	</bean>
	
	<!-- Use JtaTransactionManager, which implements PlatformTransactionManager interface -->
	<!-- For specific implementations with global transaction management -->
	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<beans>

As can be seen from the above configuration file, when configuring the JtaTransactionManager global transaction management strategy, you only need to specify the transaction manager implementation class without passing in additional transaction resources. This is because the global transaction JTA resource is provided by the application server, and the Spring container can obtain the transaction resource from the server by itself, so there is no need to use dependency injection for configuration.

3. When using the Hibernate persistence layer access technology, the configuration file of the local transaction is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	
	<!-- define data source bean -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	    <!-- Specify the driver to connect to the database -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<!-- Specify the URL to connect to the database -->
		<property name="url" value="jdbc:oracle:****" />
		<property name="username" value="****" />
		<property name="password" value="****" />
	</bean>
	
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<!-- mappingResources attribute is used to list all mapping files -->
		<property name="mappingResources">
			<list>
			    <!-- The following is used to list all PO mapping files-->
				<value>lee/MyTest.hbm.xml</value>
			</list>
		</property>
		<!-- Define the properties of Hibernate's SessionFactory -->
		<property name="hibernateProperties">
			<props>
			    <!-- Specify the connection dialect of hibernate-->
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
				<!-- Whether to create a data table based on hibernate mapping -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>
	
	<!-- Configure Hibernate's local transaction manager, use the HibernateTransactionManager class -->
	<!-- This class implements the PlatformTransactionManager interface, which is for a specific implementation using hibernate -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
<beans>


If the bottom layer adopts Hibernate persistence technology, but the transaction adopts JTA global transaction, the Spring configuration file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	
	<!-- Configure JNDI data source bean -->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
	    <!-- JNDI for container-managed data sources -->
		<property name="jndiName" value="jdbc/jpetstore" />
	</bean>
	
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<!-- mappingResources attribute is used to list all mapping files -->
		<property name="mappingResources">
			<list>
			    <!-- The following is used to list all PO mapping files-->
				<value>lee/MyTest.hbm.xml</value>
			</list>
		</property>
		<!-- Define the properties of Hibernate's SessionFactory -->
		<property name="hibernateProperties">
			<props>
			    <!-- Specify the connection dialect of hibernate-->
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
				<!-- Whether to create a data table based on hibernate mapping -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>
	
	<!-- Use JtaTransactionManager, which implements PlatformTransactionManager interface -->
	<!-- For specific implementations with global transaction management -->
	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<beans>

As can be seen from the above configuration files, no matter which persistence layer access technology is used, as long as the JTA global transaction is used, the configuration of Spring transaction management is exactly the same.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326646940&siteId=291194637