Programming transaction control related objects
Programming is to write code by using Java API. Declarative is to configure some things in the way of configuration
PlatformTransactionManager
The PlatformTransactionManager interface is the transaction manager of spring. It provides our common methods of operating transactions, that is, how transactions are controlled
method | explain |
---|---|
TransactionStatus getTransaction(TransactionDefination defination) | Gets the status information of the transaction |
void commit(TransactionStatus status) | Commit transaction |
void rollback(TransactionStatus status) | Rollback transaction |
Note: PlatformTransactionManager is an interface type, and different Dao layer technologies have different implementation classes. For example, when Dao layer technology is JDBC or mybatis: org.springframework.jdbc.datasource.datasourcetransactionmanager; When Dao layer technology is Hibernate: org.springframework.orm.hibernate5.hibernatetransaction Manager
TransactionDefinition
Maintain transaction attribute information
TransactionDefinition is the transaction definition information object, which contains the following methods
method | explain |
---|---|
int getIsolationLevel() | Gets the isolation level of the transaction |
int getPropogationBehavior() | Get propagation behavior of transaction |
int getTimeout() | Get timeout |
boolean isReadOnly | Read only |
Transaction isolation level
Setting the isolation level can solve the problems caused by transaction concurrency, such as dirty read, non repeatable read and virtual read
Dirty read: a transaction reads uncommitted data from another transaction
Non repeatability: in the same transaction, the data read twice is different
Phantom reading: if one transaction operation (DML) data represents all records and another transaction adds a piece of data, the first transaction cannot query its own modifications.
ISOLATION_DEFAULT default
ISOLATION_ READ_ Uncommitted read (resulting problems: dirty read, non heavy load read, phantom read)
ISOLATION_READ_COMMITTED read has been submitted (resulting problems: no heavy reading, unreal reading)
ISOLATION_REPEATABLE_READ is not repeatable
ISOLATION_SERIALIZABLE serialization can solve all problems
Transaction propagation behavior
Encapsulate some state information and passive information during operation
The problem of transaction uniformity when business methods call business methods. In normal development, the business layer has many methods. When a and B methods call each other, we control their transactions in advance, and the problem of transaction duplication may occur
REQUIRED: if there is no transaction at present, create a new transaction. If there is already a transaction, join it. General selection (default)
SUPPORTS: SUPPORTS the current transaction. If there is no transaction, it will be executed in a non transactional manner (no transaction)
MANDATORY: use the current transaction. If there is no transaction, an exception will be thrown
Requests_new: create a new transaction. If it is currently in a transaction, suspend the current transaction.
NOT_SUPPORTED: perform operations in a non transactional manner. If there is a transaction, suspend the current transaction
NEVER: run in non transaction mode. If there is a transaction, throw an exception
NESTED: if a transaction currently exists, it is executed within a NESTED transaction. If there is no transaction currently, an operation similar to REQUIRED is executed
Timeout: the default value is - 1. There is no timeout limit. If there is, it is set in seconds
Read only: it is recommended to set it as read-only when querying
TransactionStatus
The TransactionStatus interface provides the specific running status of transactions. The methods are described below
method | explain |
---|---|
boolean hasSavepoint() | Store rollback points |
boolean isCompleted() | Is the transaction complete |
boolean isNewTransaction() | Is this a new transaction |
boolean isRollbackOnly() | Whether the transaction is rolled back |
Declarative transaction control based on XML
Spring's declarative transaction, as its name suggests, is to process transactions in a declarative manner. The declaration here refers to declaring in the configuration file and using the declarative transaction in the spring configuration file to replace the code transaction.
The role of declarative transactions
1. Transaction management does not invade the developed components. Specifically, business logic objects will not realize that they are in transaction management. In fact, it should be the same, because transaction management is a system level service, not a part of business logic. If you want to change the transaction management plan, you only need to reconfigure it in the definition file
2. When transaction management is not required, the transaction management service can be removed as long as the settings file is modified without changing the code and recompiling, which is very convenient for maintenance
The underlying layer of Spring declarative transaction control is AOP
Implementation of declarative transaction control
Explicit matters of declarative transaction control:
Who is the pointcut? The business approach is enhanced
Who is notification? Transaction enhancement
Configuration aspect weaves transaction enhancements and business methods
0. Write dao layer and service layer
package com.zg.dao.impl; import com.zg.dao.AccountDao; import org.springframework.jdbc.core.JdbcTemplate; public class AccountDaoImpl implements AccountDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void out(String outMan, double money) { jdbcTemplate.update("update account set money=money-? where name=?",money,outMan); } public void in(String inMan, double money) { jdbcTemplate.update("update account set money=money+? where name=?",money,inMan); } }
package com.zg.service.impl; import com.zg.dao.AccountDao; import com.zg.service.AccountService; public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public void transfer(String outMan, String inMan, double money) { //The transaction needs to be started here accountDao.out(outMan,money); int i = 1/0; accountDao.in(inMan,money); //Commit transaction } }
1. Introduce tx namespace, configure transaction enhancement, and configure transaction AOP weaving
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="accountDao" class="com.zg.dao.impl.AccountDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> <!--The internal method of the target object is the tangent point--> <bean id="accountService" class="com.zg.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> </bean> <!--Configure a platform transaction manager--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> <!--transactionManager The bottom layer needs to start from dataSource Gets a control for the transaction--> <!--jdbc The template is right jdbc Simple encapsulation. The platform manager needs to connect objects when managing transactions connection,connection Injection required from data source dataSource--> </bean> <!--The namespace of the enhanced transaction for the notification transaction is tx--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes<--tx affair attributs attribute--> <tx:method name="*"/> </tx:attributes> </tx:advice> <!--to configure aop Transaction weaving--> <aop:config> <!--advisor yes Spring Specialized configuration of transaction control--> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.zg.service.impl.*.*(..))"></aop:advisor> </aop:config> </beans>
If the implementation of dao layer is not native jdbc or Mybatis, the platform manager may change accordingly
2. Test transaction control transfer business code
package com.zg.service.impl; import com.zg.dao.AccountDao; import com.zg.service.AccountService; public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } public void transfer(String outMan, String inMan, double money) { //The transaction needs to be started here accountDao.out(outMan,money); int i = 1/0; accountDao.in(inMan,money); //Commit transaction } }
Configuration of transaction parameters of pointcut method
<!--The namespace of the enhanced transaction for the notification transaction is tx--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*"/> </tx:attributes> </tx:advice>
Where, < TX: method > represents the configuration of the transaction parameters of the pointcut method, for example
< TX: attributes > is to set the attribute information of the transaction
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/> <--Here because transfer It's enhancement, so it's right transfer Separate transaction configuration. If there are other methods, copy and rewrite. A transaction can configure the attribute parameters belonging to the transaction respectively-->
nam = "*" *: represents any method
name="update *": indicates the method starting with update
Name: pointcut method name
Isolation: isolation level of transaction
Propagation: propagation behavior of transactions
Timeout: timeout
Read only: whether it is readable
Annotation based declarative transaction control
Configuring declarative transaction control using annotations
1. Write dao
package com.zg.dao.impl; import com.zg.dao.AccountDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository("accountDao") public class AccountDaoImpl implements AccountDao { @Autowired private JdbcTemplate jdbcTemplate; public void out(String outMan, double money) { jdbcTemplate.update("update account set money=money-? where name=?",money,outMan); } public void in(String inMan, double money) { jdbcTemplate.update("update account set money=money+? where name=?",money,inMan); } }
2. Write service
package com.zg.service.impl; import com.zg.dao.AccountDao; import com.zg.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service("accountService") //You can also add transaction control to the class, which means that all methods in the following class use the specified transaction control parameter @Transactional(isolation = Isolation.READ_COMMITTED) public class AccountServiceImpl implements AccountService { @Autowired private AccountDao accountDao; //The principle of proximity is the main principle @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED) public void transfer(String outMan, String inMan, double money) { //The transaction needs to be started here accountDao.out(outMan,money); int i = 1/0; accountDao.in(inMan,money); //Commit transaction } }
3. Write the application.xml configuration file
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!--Component scan--> <context:component-scan base-package="com.zg"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <!--Configure a platform transaction manager--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> <!--transactionManager The bottom layer needs to start from dataSource Gets a control for the transaction--> <!--jdbc The template is right jdbc Simple encapsulation. The platform manager needs to connect objects when managing transactions connection,connection Injection required from data source dataSource--> </bean> <!--Annotation driven transactions--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven> </beans>
Here, if there is no customized aspect class, there is no need to configure it. The pointcut and weaving framework of transaction management have been obtained through the transaction annotation and the information of the class. The underlying aspect class is provided by spring and configured by spring itself
Annotation configuration declarative transaction control resolution
1. @ Transactional modifies classes or methods that need transaction control. The attributes available for annotation are the same as xml configuration methods, such as isolation level, propagation behavior, etc.
2. If annotations are used on a class, all methods under the class are configured with the same set of annotation parameters
3. In terms of methods, different methods can adopt different transaction parameter configurations
4. Annotation driven transaction manager = "transactionmanager" > < / TX: annotation driven >