“This is the 14th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
1. Transactions are generally added to the Service layer (business logic layer) within the JavaEE three-tier structure.
Two ways to conduct transaction management operations in Spring
- Programmatic transaction management
- Declarative transaction management
Declarative transaction management
(1) Based on annotations (use)
(2) Based on XML configuration files
4. Declarative transaction management in Spring, using AOP principle at the bottom
5. Spring Transaction Management API
Provides an interface that represents the transaction manager and provides different implementation classes for different frameworks
Transaction manager:
Annotation-based declarative transactions
1. Configure the data source and the transaction manager
2. Turn on transaction annotations
<! -- Configure transaction manager -->
<bean id="tranctionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druiddatasource"></property>
</bean>
<! -- Enable transaction annotations -->
<tx:annotation-driven transaction-manager="tranctionManger"></tx:annotation-driven>
Copy the code
Add transaction annotations above the Service class (or above the methods in the class)
(1) The @Transactional annotation is added to classes or methods
(2) If you add this annotation to a class, all methods in the class add transactions
(3) Add a transaction to the method if the annotation is added to the method
Parameter configuration for declarative transactions
Add the @Transactional annotation to the Service class to configure Transactional parameters
Seven parameters:
propagation
— Transaction propagation behavior
Propagation properties | describe |
---|---|
REQUIRED | If a transaction is running, the current method runs within that transaction; otherwise, a new transaction is started and runs within its own transaction |
REQUIRED_NEW | The current method must start a new transaction and run within its own transaction, and should suspend it if a transaction is running |
SUPPORTS | If a transaction is running, the current method runs within that transaction. Otherwise it may not run in a transaction |
NOT_SUPPORTE | The current method should not run in a transaction. If there are transactions running, suspend them |
MANDATORY | The current method must run inside a transaction and throw an exception if no transaction is running |
NEVER | The current method should not run in a transaction. Throw an exception if there are transactions running |
NESTED | If a transaction is running, the current method should run within a nested transaction of that transaction. Otherwise, a new transaction is started and runs within its own transaction |
Specific cases:
PROPAGATION_REQUIRED
If method A has A transaction, after calling method B, method B uses the transaction in method A
If method A has no transaction, after calling method B, A new transaction is created for use by method A and method B
PROPAGATION_REQUIRED_NEW
Method B is called at REQUIRED_NEW level using method A, which is REQUIRED. When method B is executed, method B automatically creates A new transaction and method A suspends. At this point, there are two transactions, assuming that method B reports an exception rollback, method A may still commit; Suppose method A rolls back unexpectedly, but method B has been committed, and method B does not roll back.
PROPAGATION_SUPPORTS
Assume that you are currently in a transaction. That is, it is executed as a transaction. Assuming that it is not currently in a transaction, it is executed nontransactionally
PROPAGATION_MANDATORY
Must be executed in a transaction. Otherwise, the method throws an exception
PROPAGATION_NOT_SUPPORTED
Method A has A transaction, and method B has A NOT_SUPPORTED isolation level. When A method B executes, the transaction of method A is suspended automatically, and method B runs with no transaction conditions and does not roll back if an error occurs.
PROPAGATION_NEVER
Method A has A transaction, method B has A PROPAGATION_NEVER isolation level, and throws an exception when executed to method B
PROPAGATION_NESTED
Method A has A transaction, and method B has A PROPAGATION_NESTED isolation level. When method B is executed, A new transaction is created for both methods to run
isolation
— Transaction isolation level
Dirty read: Uncommitted data reads data from another uncommitted transaction
Unrepeatable read: Data after a committed transaction is read in an uncommitted transaction
Phantom read: an uncommitted transaction reads data added by another committed transaction
Set the isolation level to resolve the problem
Dirty read | Unrepeatable read | Phantom read | |
---|---|---|---|
READ UNCOMMITTED The READ is not committed | There are | There are | There are |
READ COMMITED The READ is committed | There is no | There are | There are |
REPEATABLE READ REPEATABLE READ | There is no | There is no | There are |
The SERIALIZABLE serialization | There is no | There is no | There is no |
timeout
timeout
(1) The transaction needs to be committed within a certain period of time. If it is not committed, it will be rolled back
(2) The default value is -1, and the setting time is calculated in seconds
readonly
Whether the read-only
(1) Read: query operation; write: add, modify and delete operation
(2) The default value is false, indicating that the query and add, modify and delete operations can be performed
(3) Set the value of readOnly to true
rollbackfor
The rollback
Sets which exceptions occur for transaction rollback
noRollbackFor
Don’t roll
Sets which exceptions do not roll back transactions
Declarative transactions based on configuration files
1. Configure the transaction manager
<! -- Configure transaction manager -->
<bean id="tranctionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druiddatasource"></property>
</bean>
<! -- Enable transaction annotations -->
<tx:annotation-driven transaction-manager="tranctionManger"></tx:annotation-driven>
Copy the code
2. Configure notifications
<! -- Configure notifications -->
<tx:advice id="interceptor">
<! -- Set transaction parameters -->
<tx:attributes>
<! -- Specifies which rule method adds transactions to -->
<tx:method name="add*" propagation="REQUIRED" isolation="REPEATABLE_READ"/>
</tx:attributes>
</tx:advice>
Copy the code
3. Configure pointcuts and facets
<! Configure pointcuts and facets -->
<aop:config>
<! Configure pointcuts -->
<aop:pointcut id="p" expression="execution(* com.jxau.*.*.*(..) )"/>
<! Configure the section and weave transaction notifications into the section
<aop:advisor advice-ref="interceptor" pointcut-ref="p"></aop:advisor>
</aop:config>
Copy the code
Full annotations implement declarative transactions
Create a configuration class instead of an XML configuration file
@Configuration
@EnableTransactionManagement // Start the transaction
@ComponentScan(basePackages = "com.jxau")// Component scan package
public class SpringTransactional {
@Bean
public DruidDataSource getDruidDataSource(a){
// Create an instance and place it in the SpringIoc container
DruidDataSource druidDataSource=new DruidDataSource();
druidDataSource.setUrl("JDBC: mysql: / / 127.0.0.1:3306 / springdb");
druidDataSource.setUsername("root");
druidDataSource.setPassword("");
druidDataSource.setMaxActive(20);
return druidDataSource;
}
@Bean
public JdbcTemplate getJdbcTemplate(DruidDataSource druidDataSource){
// From the IOC container corresponds to the instance by type
return new JdbcTemplate(druidDataSource);
}
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DruidDataSource druidDataSource){
return newDataSourceTransactionManager(druidDataSource); }}Copy the code
The test class
public class Test {
@org.junit.Test
public void aa(a) {
ApplicationContext context=new AnnotationConfigApplicationContext(SpringTransactional.class);// Load the configuration class
UserService service=(UserService) context.getBean("userService"); service.add(); }}Copy the code