手写spring事物管理,了解spring事物运行原理!

																**了解spring事物的本质**

spring事物的使用


不管我们使用spring集成mybatis、JdbcTemplate等,使用事物的时候只需要一个注解@Transactional,非常的方便,可能很多人没有想过这个注解是如何完成事物的工作的,今天就和大家一起探讨一下。

原生事物的实现:

package com.suning.ics.transaction;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * Created by 18077616 on 2019/9/12.
 */
@Service
public class TransacionService {

    @Autowired
    private MyJDBCTemplate template;

    @Autowired
    private MyConnectionManage connectionManage;

    //开启事物的注解
    //事物传播
    @MyTransactional
    public void insertUser() throws SQLException {
        //事物在 template 里做不对,执行sql时候不知道是否需要开启,且。。。
        //可以在这里做事物处理,但是每次都要写,不友好
        Connection connection = connectionManage.getConnection();
        connection.setAutoCommit(false);
        try {
            template.execute("insert INTO  USER VALUES ('name1')");
            template.execute("insert INTO  USER VALUES ('name2')");
            //            template.execute("delete from user where name= 'name1'");
            int i = 1 / 0;
        } catch (Exception e) {
            connection.rollback();
        } finally {
            connection.close();
        }

    }
}

:spring事物的实现:

定义我们自己的事物注解:

package com.suning.ics.transaction;

import java.lang.annotation.*;

/**
 * 开启事物的注解
 * Created by 18077616 on 2019/9/12.
 */
@Documented
@Target(ElementType.METHOD)
//@Retention(RetentionPolicy.RUNTIME)
public @interface MyTransactional {
}

注解的使用:

package com.suning.ics.transaction;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * Created by 18077616 on 2019/9/12.
 */
@Service
public class TransacionService {

    @Autowired
    private MyJDBCTemplate template;

    @Autowired
    private MyConnectionManage connectionManage;

    //开启事物的注解
    //事物传播
    @MyTransactional
    public void insertUser() throws SQLException {
        //事物在 template 里做不对,执行sql时候不知道是否需要开启,且。。。
        //可以在这里做事物处理,但是每次都要写,不友好
//        Connection connection = connectionManage.getConnection();
//        connection.setAutoCommit(false);
        try {
            template.execute("insert INTO  USER VALUES ('name1')");
            template.execute("insert INTO  USER VALUES ('name2')");
            //            template.execute("delete from user where name= 'name1'");
            int i = 1 / 0;
        } catch (Exception e) {
//            connection.rollback();
        } finally {
//            connection.close();
        }

    }
}

自己简单实现jdbcTemplate,主要用户sql执行,参数注入及结果的映射

package com.suning.ics.transaction;

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

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

/**
 * 本质就是集中处理sql操作,参数绑定,结果映射等
 * Created by 18077616 on 2019/9/12.
 */
@Component
public class MyJDBCTemplate {

    @Autowired
    private MyConnectionManage connectionManage;

    /**
     * 这里去掉事物管理(mubastis,JdbcTemplate等集成spring后,事物都交给spring管理)
     * @param sql
     * @throws SQLException
     */
    public void execute(String sql) throws SQLException {
        Connection connection = connectionManage.getConnection();
        Statement statement = connection.createStatement();
        statement.execute(sql);
//        try {
//            connection.setAutoCommit(false);  //关闭自动提交
//            Statement statement = connection.createStatement();
//            statement.execute(sql);
//            connection.commit();
//        } catch (SQLException e) {
//            try {
//                //数据回滚,在这里可以看到事物回滚是基于数据库连接的
//                connection.rollback();
//            } catch (SQLException e1) {
//                e1.printStackTrace();
//            }
//            e.printStackTrace();
//        }finally {
//            //连接的关闭可能关闭了,也可能放回连接池进行复用
//            connection.close();
//            System.out.println("关闭连接");
//        }
    }
}

连接管理类:这是一个关键点,保证我们每个线程的连接是同一个连接,事物的回滚的可行性及正确性

package com.suning.ics.transaction;

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

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

/**
 * Created by 18077616 on 2019/9/12.
 */
//spring 托管创建实例,默认是单利的,那所有线程用的是同一个实例
@Component
public class MyConnectionManage {

    @Autowired
    DataSource dataSource1;

    //因为事物是基于连接的,不同的请求不能用同一个连接
    //每条sql获取新的连接是不行的
    private ThreadLocal<Connection> connections = new ThreadLocal<>();
    Connection connection = null;

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

        return connection;
    }
}

spring aop 进行事物的统一管理:

package com.suning.ics.transaction;

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;

/**
 * Created by 18077616 on 2019/9/12.
 */
@Component
@Aspect
public class MyTransactionalAspect {

    @Autowired
    MyConnectionManage connectionManage;

    /**
     * 加了注解的,方法前后执行该代码
     * @return
     */
    @Around("@annotation(MyTransactional)")
    public Object doTransactional(ProceedingJoinPoint joinPoint)throws Throwable{
        Object r = null;
        Connection connection = connectionManage.getConnection();

        try {
            //原方法执行前执行
            connection.setAutoCommit(false);
            r = joinPoint.proceed();  //执行原方法
            connection.commit();
            //原方法执行后执行
        } catch (Exception e) {
            connection.rollback();
        }finally {
            connection.close();
        }
        return r;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值