Spring 事务 注解@Transaction 用法

在实际开发中,对于一组数据库操作特别是增删改操作,为了保证原子性,通过需要用事务来控制,要么全部成功,要么全部失败。Spring中可以通过注解@Transaction

常用的方法如下:

@Transactional
public void testTransaction(User user) {
    int rowNum = userMapper.insertUser(user);
    List<User> userList = userMapper.selectAllUsers();
}

这里将两个操作insert和select当作原子操作,如果在testTransaction方法中有异常,则回滚。(注意:这个事务是MySQL层控制,回滚的操作也是MySQL控制的)。

需要注意的问题:

(1)尽可能将MySQL执行语句往方法体后面靠:

@Transactional
public void testTransaction(User user) {
    int rowNum = userMapper.insertUser(user);
    doSomething(); // 这个doSomthing 可能耗时较长
    List<User> userList = userMapper.selectAllUsers();
}

如果可以移动的话,可以将doSomething()可能耗时较长,移动到int rowNum=userMapper.insertUser(user)的前面,即:

@Transactional
public void testTransaction(User user) {
    doSomething(); // 这个doSomthing 可能耗时较长
    int rowNum = userMapper.insertUser(user);  
    List<User> userList = userMapper.selectAllUsers();
}

因为,MySQL事务的commit语句是在第一次执行MySQL相关语句开始,一直到方法的结束。

(2)设置事务的超时时间(如果不设置默认是-1是无限长)

@Transactional(timeout = 5)
public void testTransaction(User user) throws InterruptedException {
    Thread.sleep(2000);
    List<User> userList = userMapper.selectAllUsers(); // 耗时:1s
    int rowNum = userMapper.insertUser(user); // 耗时 1s
    Thread.sleep(3000);
}

加入另外两个MySQL相关的操作耗时都是1s,则上述事务是不会报超时异常。

timeout的计算的事务超时 = 最后一个MySQL语句耗时 + 以及最后一个MySQL之前的所有耗时。因此,上述耗时为2s+1s+1s=4s,没有超过5s,因此不会报事务超时异常,这个需要特别注意,如果想了解具体原理,可以查看源码,或者看该文档:http://jinnianshilongnian.iteye.com/blog/1986023

发布了164 篇原创文章 · 获赞 113 · 访问量 68万+

猜你喜欢

转载自blog.csdn.net/timchen525/article/details/81517748