spring中的事务框架

52 阅读2分钟

事务框架

框架并不提供对事务的实现,但是提供规约,接口如下:

public interface PlatformTransactionManager extends TransactionManager {
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}

如果在类路径中,发现JPA框架,事务的实现将采用JPA提供的方式,如下:

public class JpaTransactionManager 
extends AbstractPlatformTransactionManager 
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
//...
}

其中==AbstractPlatformTransactionManager== 继承 ==PlatformTransactionManager==,如下;

public abstract class AbstractPlatformTransactionManager 
implements PlatformTransactionManager, Serializable {

这是spring框架对事务支持的大概方式。

声明式事务

这是框架建议使用的方式,粒度到方法级别(这也是一直被诟病的地方),如下:

public class TransactionTest{

     @Transactional(rollbackFor = Exception.class)
    public String doFunc(){

        try{
                //其他业务逻辑
                //如果doFunc()函数正常结束,事务自动提交
        }
        catch(Exception ex){
        	//如果发生异常,事务会自动回滚
            throw new ex;
        }
    }

}

有几个限制:

  • doFunc()方法必须是public才可以,spring认为只有通过外部调用才会触发事务,private只提供内部调用不触发事务;
  • @Transactional(rollbackFor = Exception.class)必须指定触发回滚的异常类型,因为默认只有RuntimeException类型异常才会触发回滚

声明式事务最小粒度到方法级别,如果领域划分不清晰,会导致相关事务很大,如果数据库隔离级别设定不合理,将会非常占用资源,所以很多项目中都使用了编程式事务。

编程式事务

在事务框架中介绍了事务实现的大概方式,如果类路径中提供了JPA,spring boot会根据配置文件自动生成JpaTransactionManager的bean,在项目中可以直接使用,如下:

@Autowired
JpaTransactionManager jpaTransactionManager;

注入后既可使用,比较方便。 如果允许,建议把相关内容封装在自定义的公共里面 使用方式也比较简单,如下:

//获取当前事务状态
private TransactionStatus status;
public void beginTransaction()
    {
        status = jpaTransactionManager.getTransaction(TransactionDefinition.withDefaults());
    }
//提交
    public void commit()
    {
        jpaTransactionManager.commit(status);
    }
//回滚
    public void rollback()
    {
        jpaTransactionManager.rollback(status);
    }

通过上面的简单封装,如下示例调用:

 public void add()
    {
        try
        {
            this.beginTransaction();
            // do something            
            this.commit(); 
        }
        catch (RuntimeException ex)
        {
            this.rollback();
        }

    }

大概就这么简单。

针对嵌套事务需要构建还原点,对开发人员要求比较高,项目中并不建议使用。

事务扩展知识

这里提供一个链接,其中对 事务传递、隔离级别做了介绍,有兴趣的朋友可以拜读:

www.cnblogs.com/yixianyixia…