spring使用Aop事务失效问题

spring使用Aop事务失效问题

问题:项目中碰到在同一个类中(JDK动态代理),非事务方法调用一个有事务方法,会使得整个事务失效

问题重现

利用mysql中ReplicationDriver的特性:如果加了@transaction注解就从主库取数据,而加@transaction(readOnly=true)时则到从库取数据的原理

现主库有数据:

{
    "id": 1,
    "userName": "test_test",
    "password": "test_replica",
    "createTime": 1534591529000,
    "modifyTime": 1534591531000,
    "isDelete": 1
}

从库有数据:

{
    "id": 1,
    "userName": "test_test",
    "password": "test_replica",
    "createTime": 1534591529000,
    "modifyTime": 1534591531000,
    "isDelete": 0
}

UserService.java:

public interface UserService {

    public void selectUserFromMaster() throws JsonProcessingException;

    public void selectUsers() throws JsonProcessingException;

}

实现类UserServiceImpl.java:

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Transactional
    public void selectUserFromMaster() throws JsonProcessingException {
//        TransactionDebugUtils.transactionRequired("UserService.selectUserFromMaster");
        UserDo userDo = userDao.selectByPrimaryKey(1L);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(userDo));
    }


    public void selectUsers() throws JsonProcessingException {
        selectUserFromMaster();
    }

}

申明全局事务,所有以select为前缀都从库取数据:

<tx:annotation-driven transaction-manager="transactionManager"/>

<tx:advice id="txAdvice">
   <tx:attributes>
       <tx:method name="*" propagation="REQUIRED"/>
       <tx:method name="select*" read-only="true"/>
   </tx:attributes>
</tx:advice>

<aop:config>
   <aop:pointcut id="pointCut" 
   expression="execution(* com.**.persistent.dao.*.*(..))"></aop:pointcut>
   <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
</aop:config>

测试案例:

public class UserServiceTest extends BaseTest {


    @Autowired
    private UserService userService;

    @Test
    public void selectUserFromMasterTest() throws JsonProcessingException {
        userService.selectUserFromMaster();
    }


    @Test
    public void selectUsersTest() throws JsonProcessingException {
        userService.selectUsers();
    }
}

测试结果:


[selectUserFromMasterTest](主库数据):
{
    "id": 1,
    "userName": "test_test",
    "password": "test_replica",
    "createTime": 1534591529000,
    "modifyTime": 1534591531000,
    "isDelete": 1
}

[selectUsersTest](从库):
{
    "id": 1,
    "userName": "test_test",
    "password": "test_replica",
    "createTime": 1534591529000,
    "modifyTime": 1534591531000,
    "isDelete": 0
}

解决方案

首先在xml中加入:

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

然后修改UserServiceImpl.java文件:

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Transactional
    public void selectUserFromMaster() throws JsonProcessingException {
        TransactionDebugUtils.transactionRequired("UserService.selectUserFromMaster");
        UserDo userDo = userDao.selectByPrimaryKey(1L);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(userDo));
    }


    public void selectUsers() throws JsonProcessingException {
        ((UserService)AopContext.currentProxy()).selectUserFromMaster();
    }

}

运行测试案例selectUsersTest结果:

[selectUsersTest](主库):
{
    "id": 1,
    "userName": "test_test",
    "password": "test_replica",
    "createTime": 1534591529000,
    "modifyTime": 1534591531000,
    "isDelete": 1
}

经测试,如果同样是类代理模式中(CGLIB动态代理),在这样的一样环境,事务也还是会失效,解决方法和这个一样

一个测试获取事务的工具类文章:

tips-for-debugging-springs-transactional-annotation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值