日期:2014-05-19  浏览次数:20704 次

Spring 的transaction 注解事务 传播性和隔离性的问题
Java code



        @Autowired
    ITestDAO dao ;
//设置timeout 2秒 超时就报异常  
@Transactional(timeout=2,rollbackFor=Exception.class)
    public int save(Test t) throws Exception {
        System.out.println("进入**");
        for (int i = 0; i < 500000; i++) {
            System.out.println("*");
        }
        
        System.out.println("进入保存");
        dao.save(t);//数据库插入操作
        System.out.println("退出保存");
         }



我设置了事务超时,但是为什么超时后 异常显示了,但是数据也插入却没用回滚?


spring中的timeout是默认为-1 就是永远不超时。但是我设置了2秒。 (for 循环50W 有2秒时间吧?) 异常报出来
但是hibernate在控制台也打印出sql语句 并且插入进去数据了。这并不是我预期的结果。
应该是异常后 回滚了。所以想请教下:

这个timeout并不是我能设置出来的时间吗?
最近看这方面的知识,事务传播性和隔离性。

为了防止脏读和重复读、幻读 
(isolation)的隔离级别我只能使用串行化?

事务的传播性也正在努力测试中、

------解决方案--------------------
timeout应该是对应的connection的超时吧
System.out.println("进入保存");
dao.save(t);//数据库插入操作
throw new Exception();
System.out.println("退出保存");

这样就可以测试了,如果数据插进去了,说明你的事务配置不正确,事务并没有开启
------解决方案--------------------
默认遇到throw new RuntimeException("...");会回滚
需要捕获的throw new Exception("...");不会回滚

// 指定回滚
@Transactional(rollbackFor=Exception.class) 
public void methodName() {
// 不会回滚
throw new Exception("...");

//指定不回滚
@Transactional(noRollbackFor=Exception.class)
public ItimDaoImpl getItemDaoImpl() {
// 会回滚
throw new RuntimeException("注释");


// 如果有事务,那么加入事务,没有的话新建一个(不写的情况下)
@Transactional(propagation=Propagation.REQUIRED) 
// 容器不为这个方法开启事务
@Transactional(propagation=Propagation.NOT_SUPPORTED)
// 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.REQUIRES_NEW) 
// 必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.MANDATORY)
// 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.NEVER) 
// 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
@Transactional(propagation=Propagation.SUPPORTS) 

 
@Transactional(propagation=Propagation.NESTED) 
// readOnly=true只读,不能更新,删除 
@Transactional (propagation = Propagation.REQUIRED,readOnly=true) 
// 设置超时时间
@Transactional (propagation = Propagation.REQUIRED,timeout=30)
// 设置数据库隔离级别
@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)
------解决方案--------------------
你是基于注解的配置。
@Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
默认的 @Transactional 设置如下:
事务传播设置是 PROPAGATION_REQUIRED
事务隔离级别是 ISOLATION_DEFAULT
事务是 读/写
事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚,需要我们在外部用try/catch语法对调用该方法的地方进行包含 @Transactional,也就是在方法级别加如类似于@Transactional(rollbackFor=Exception.class)
在同一个类中一个方法调用另一个有事务的方法,事务是不会起作用的。
Java code

public interface PersonService {
//删除指定id的person
public void delete(Integer personid) ;

//删除指定id的person,flag
public void delete(Integer personid,boolean flag) ;
}

public class PersonServiceBean implements PersonService {
private JdbcTemplate jdbcTemplate;

public void delete(Integer personid){
try{
this.delete(personid,true)
System.out.println("dele