“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

timeouttimeout

(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

readonlyWhether 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

rollbackforThe rollback

Sets which exceptions occur for transaction rollback

noRollbackForDon’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