Spring 事务 注解@Transaction 用法

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

常用的方法如下:

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

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

需要注意的问题:

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

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

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

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

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

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

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

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

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

上一篇:MySQL - 当前读和快照读


下一篇:braintree 支付