zoukankan      html  css  js  c++  java
  • spring @Transactional 声明式事务

    项目地址:git@github.com:witaste/transaction-annotation.git

    情景一:

    A external method calls a method of the target object 

    外部方法调用目标对象的事务方法,异常逐层抛出,最终由a() 抛出,可以回滚。

    @Service
    public class FooServiceImpl implements FooService {
    
        @Autowired
        private FooMapper fooMapper;
    
        @Transactional(propagation = Propagation.REQUIRED)
        public void a() {
            b();
        }
    
        public void b() {
            fooMapper.insert(new Foo("1"));
            int i = 1 / 0;
            fooMapper.insert(new Foo("2"));
        }
    }

    情景二:

    The target object call another method of the target object  

    不能开启事务,插入了一条数据。

    @Service
    public class FooServiceImpl implements FooService {
    
        @Autowired
        private FooMapper fooMapper;
    
        public void a() {
            try {
                b();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    
        @Transactional(propagation = Propagation.REQUIRED)
        public void b() {
            fooMapper.insert(new Foo("1"));
            int i = 1 / 0;
            fooMapper.insert(new Foo("2"));
        }
    }

    情景二解决办法:

    办法1.

    将b() 转移到OtServiceImpl 中即可。

    办法2.

    使用代理对象调用b() , 即:

    ((FooService) AopContext.currentProxy()).b();

    需要引入jar包

            <!-- aspectj -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.8.7</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.7</version>
            </dependency>

    需要暴露代理:

    <aop:aspectj-autoproxy expose-proxy="true"/>

    修改后的类:

    @Service
    public class FooServiceImpl implements FooService {
    
        @Autowired
        private FooMapper fooMapper;
    
        public void a() {
            try{
                ((FooService) AopContext.currentProxy()).b();
            }catch(Exception e){
                System.out.println(e.getMessage());
            }
        }
    
        @Transactional(propagation = Propagation.REQUIRED)
        public void b() {
            fooMapper.insert(new Foo("1"));
            int i = 1 / 0;
            fooMapper.insert(new Foo("2"));
        }
    }

    PS:其他复杂情景不做考虑

    官方文档:http://docs.spring.io/spring/docs/4.2.0.RC1/spring-framework-reference/htmlsingle/#transaction-declarative-annotations

    附运行日志:

    情景一: 

    16:02:27.372 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
    16:02:27.372 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]
    16:02:27.403 [main] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [33362707, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver] will be managed by Spring
    16:02:27.403 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ooo Using Connection [33362707, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver]
    16:02:27.403 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ==>  Preparing: select sys_guid() from dual 
    16:02:27.513 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ==> Parameters: 
    16:02:27.872 [main] DEBUG cn.zno.dao.FooMapper.insert - ooo Using Connection [33362707, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver]
    16:02:27.872 [main] DEBUG cn.zno.dao.FooMapper.insert - ==>  Preparing: insert into FOO (ID, NAME) values (?, ?) 
    16:02:27.872 [main] DEBUG cn.zno.dao.FooMapper.insert - ==> Parameters: 220CFD8EE4A60CF3E053433210AC3DFB(String), 1(String)
    16:02:27.903 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]
    16:02:27.950 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization rolling back SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]
    16:02:27.950 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]

    情景二:

    16:09:12.544 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
    16:09:12.544 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@db15e1] was not registered for synchronization because synchronization is not active
    16:09:12.622 [main] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [24683438, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver] will not be managed by Spring
    16:09:12.622 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ooo Using Connection [24683438, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver]
    16:09:12.622 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ==>  Preparing: select sys_guid() from dual 
    16:09:12.732 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ==> Parameters: 
    16:09:12.794 [main] DEBUG cn.zno.dao.FooMapper.insert - ooo Using Connection [24683438, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver]
    16:09:12.794 [main] DEBUG cn.zno.dao.FooMapper.insert - ==>  Preparing: insert into FOO (ID, NAME) values (?, ?) 
    16:09:12.794 [main] DEBUG cn.zno.dao.FooMapper.insert - ==> Parameters: 220D15B5E3891024E053433210AC7FE0(String), 1(String)
    16:09:12.841 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@db15e1]
    / by zero

    情景二改:

    16:12:13.466 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
    16:12:13.482 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]
    16:12:13.513 [main] DEBUG o.m.s.t.SpringManagedTransaction - JDBC Connection [33362707, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver] will be managed by Spring
    16:12:13.513 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ooo Using Connection [33362707, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver]
    16:12:13.513 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ==>  Preparing: select sys_guid() from dual 
    16:12:13.622 [main] DEBUG c.zno.dao.FooMapper.insert!selectKey - ==> Parameters: 
    16:12:13.685 [main] DEBUG cn.zno.dao.FooMapper.insert - ooo Using Connection [33362707, URL=jdbc:oracle:thin:@//172.16.50.67:1521/orcl, UserName=E_CHANNEL, Oracle JDBC driver]
    16:12:13.685 [main] DEBUG cn.zno.dao.FooMapper.insert - ==>  Preparing: insert into FOO (ID, NAME) values (?, ?) 
    16:12:13.685 [main] DEBUG cn.zno.dao.FooMapper.insert - ==> Parameters: 220D207E0A56111CE053433210ACAD95(String), 1(String)
    16:12:13.716 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]
    16:12:13.747 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization rolling back SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]
    16:12:13.747 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14d3d6d]
    / by zero
  • 相关阅读:
    程序员学习提高必看的一篇文章
    SpringAOP拦截器的代理机制
    springboot03_RabbitMQ
    Docker_02
    Docker_01
    Redis_02
    Redis_01
    关于Linux下内存和Swap
    密码学DAY2
    密码学DAY1_02
  • 原文地址:https://www.cnblogs.com/zno2/p/4767565.html
Copyright © 2011-2022 走看看