前言
众所周知,Spring 的事务属性众多,楼主今天将对 Spring 最常用的事务 —— 声明式事务,进行彻底的解释,包括楼主也写了很多的测试例子。代码地址: 使用 tk-mybatis 的 demo 测试了 Spring 的事务
readOnly 属性
该属性的文档中说道:这不是一个百分百限制读操作之外的属性。
什么意思呢?虽然从字面意思看,是只读,但具体看数据库的实现。
mysql 数据库中,如果设置了这个属性,那么驱动将返回一个异常。
oracle 和 sqlServer 则不会,他们会忽略错误。
因此,在不同的数据库下使用要注意这点。
timeout
该属性单位是秒,不是毫秒。
从字面上看,是定义这个事务的超时时间。
我们会想当然的认为这是从事务的方法开始到方法的结束。
但,不是这样的。
是从事务方法的开始,到 SQL 语句执行的结束,因此,SQL 语句后面的代码执行时间都不算在 timeout 中的。
这点非常重要。
这样将导致下面的代码可能无法达到你想要的结果:
@Transactional(timeout = 3)
public void timeOut() {
userInfoMapper
.insert(new UserInfo().setUsername("timeout").setPassword("timeout"));
Thread.sleep(3100);
}
代码中,我们想让这个事务耗时超过 3 秒,那么就可以触发 timeout ,让 insert 无法提交。然而这时不可能的。因为,我们刚刚说,Sql 执行结束后,超时的计时就结束了。
而下面的例子则可以正确的触发 timeout:
@Transactional(timeout = 3)
public void timeOut() {
Thread.sleep(3100);
userInfoMapper
.insert(new UserInfo().setUsername("timeout").setPassword("timeout"));
}
代码中,从事务的开始到 sql 执行结束的总时间超过了 timeout 设定的时间。成功触发 timeout 机制 —— 抛出异常。
rollbackFor 和 noRollbackFor
定义一个 Class 数组,需要继承自 Throwable,也就是异常。
事务需要回滚,那么什么样的异常才能让事务回滚?
默认是 RuntimeException 和 Error。代码如下:
用户可以自定义回滚类似和反回滚类型。
上面的两个属性是相反的。
rollbackForClassName 和 noRollbackForClassName
这两个其实和上面的是一样的功能,只是这里使用了字符串,在某些类加载器不同的场合,也许有用武之地。注意,这里只需要写简单类名即可,无需写全类名。
网友评论