Manual realize their spring Affairs notes

  spring Affairs is based on the same data connection to achieve, realize this is the key to spring the transaction, the transaction will be the key point of spring is in the transaction regardless of db operations performed several times, always using the same database connection. By looking at the source code, we can see the spring following the transaction realization of ideas

 

  This is one of the key points is how to ensure the commit, rollback, acquired in a transaction connected to the same database as well as to agents by aop database connection. code show as below

  Build your own transaction manager, using threadlocal to ensure that acquired a thread within the same database connection

package com.jlwj.custom;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;


/**
 * Created by Administrator on 2019/8/31.
 */
@Component
public class MyTransactionManager {

    private ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;

    public Connection getConnection(){
        Connection connection = null;
        if(threadLocal.get()!=null){
            connection = threadLocal.get();
        }else{
            try {
                connection =  dataSource.getConnection();
                threadLocal.set(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return  connection;
    }

}

  Custom annotation

package com.jlwj.custom;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Administrator on 2019/8/31.
 */

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTransactionAnnotation {
}

  Custom jdbcTemplate simplified operation db

package com.jlwj.custom;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * Created by Administrator on 2019/8/31.
 */
@Component
public class MyJdbcTemplate {
    @Autowired
    private MyTransactionManager transactionManager;


    public void execute(String sql,@Nullable Object... args) throws SQLException {
        Connection connection = transactionManager.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < args.length; i++) {
            if(args[i] instanceof Integer){
                preparedStatement.setInt(i+1, (Integer) args[i]);
            }else if(args[i] instanceof String){
                preparedStatement.setString(i+1, (String) args[i]);
            }
        }
        preparedStatement.execute();


    }
}

  aop section, add a method to our custom annotations enhanced, open affairs

package com.jlwj.custom;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * Created by Administrator on 2019/8/31.
 */
@Aspect
@Component
public class Aop {

    @Autowired
    private MyTransactionManager myTransactionManager;

    @Around("@annotation(com.jlwj.custom.MyTransactionAnnotation)")
    public Object doTransaction(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object o = null;
        Connection connection = myTransactionManager.getConnection();
        try {
            connection.setAutoCommit(false);
            o = proceedingJoinPoint.proceed();
            connection.commit();

        } catch (SQLException e) {
            e.printStackTrace();
            connection.rollback();
        }finally {
            connection.close();
        }
        return o;
    }
}

  Test and test-class service

package com.jlwj.service;

import com.jlwj.custom.MyJdbcTemplate;
import com.jlwj.custom.MyTransactionAnnotation;
import com.jlwj.custom.MyTransactionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Created by Administrator on 2019/8/31.
 */
@Service
public class TransactionTestService2 {

    @Autowired
    private MyJdbcTemplate myJdbcTemplate;

    @Autowired
    private MyTransactionManager transactionManager;

    @MyTransactionAnnotation
    public void addUser(String userName,Integer userId){
        String sql1 = "insert into t_user(user_id,user_name,password,phone) values(?,?,?,?)";
        String sql2 = "insert into t_log(content)values (?)";
        try {
            myJdbcTemplate.execute(sql1,userId,userName,"1231456","123213213123");
            myJdbcTemplate.execute(sql2,userName);
//            int a = 1/0;
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }

    public void addUser2(String userName,Integer userId){
        String sql1 = "insert into t_user(user_id,user_name,password,phone) values(?,?,?,?)";
        String sql2 = "insert into t_log(content)values (?)";
        try {
            myJdbcTemplate.execute(sql1,userId,userName,"1231456","123213213123");
            myJdbcTemplate.execute(sql2,userName);
            int a = 1/0;
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }


}
package com.jlwj;

import com.jlwj.service.TransactionTestService;
import com.jlwj.service.TransactionTestService2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class CustomTransactionApplicationTests {


    @Autowired
    private TransactionTestService transactionTestService;

    @Autowired
    private TransactionTestService2 transactionTestService2;


    @Test
    public void contextLoads() {
        transactionTestService.addUser("wangwu",3);
    }

    @Test
    public void contextLoad2() {
        transactionTestService2.addUser("qwe",7);
    }

    @Test
    public void contextLoad3() {
        transactionTestService2.addUser2("123",8);
    }

}

  For convenience, a built spingboot project, depending on the configuration and the following

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
spring:
  datasource:
    druid:
      url: jdbc:mysql://127.0.0.1:3306/test02?characterEncoding=utf-8&serverTimezone=UTC
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
      initial-size: 1
      max-active: 20
      max-wait: 6000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=2000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 1
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false

 

Guess you like

Origin www.cnblogs.com/hhhshct/p/11442011.html