Spring对事务的支持

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring对事务的支持相关的知识,希望对你有一定的参考价值。

1、ThreadLocal

  在写Spring对事务的支持之前要先了解一下ThreadLocal,当多个线程访问同一个成员变量时,如果这个变量不做处理,那肯定会造成线程不安全的问题啊。使用ThreadLocal就可以解决这个问题,ThreadLocal为每一个线程创建变量的一个副本,这样线程操作的其实是各自的副本,就不会产生线程不安全的问题。下面看个例子:

public class ThreadLocalTest {
    private ThreadLocal<Integer> num=new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };

    Integer getNextNum(){
        num.set(num.get()+1);
        return num.get();
    };

    public static void  main(String[] args){
        ThreadLocalTest th=new ThreadLocalTest();
        Test t1=new Test(th);
        Test t2=new Test(th);
        Test t3=new Test(th);
        t1.start();
        t2.start();
        t3.start();
    }
} 

  

public class Test  extends Thread{    private ThreadLocalTest th;    public Test(ThreadLocalTest th) {        this.th = th;    }    @Override    public void run() {        for (int i=0;i<3;i++){            System.out.println("thread["+Thread.currentThread().getName()+"] th["+th.getNextNum()+"]");        }    }}
//运行结果
thread[Thread-1] th[1]
thread[Thread-0] th[1]
thread[Thread-0] th[2]
thread[Thread-0] th[3]
thread[Thread-2] th[1]
thread[Thread-2] th[2]
thread[Thread-2] th[3]
thread[Thread-1] th[2]
thread[Thread-1] th[3]

  

运行结果显示了,虽然三个线程同时访问了一个对象,但是并没有互相影响,成员变量都是从初始值开始的。

  ThreadLocal有四个方法:

  1、protectd T initiaValue():给变量设置初始值

  2、public T get():获取当前线程当前变量的值

  3、public void set(T value):给当前线程的副本设值

  4、public void remove() :删除当前线程的副本

2、Spring对事务管理的支持

  spring提供了三个接口对事务进行管理,然后提供了实现类对不同的持久层框架进行支持。

  三个接口分别是:

  1、TransactionDefinition:定义了事务的属性。

    a、事务传播行为

    b、事务隔离级别

    c、事务超时

    d、是否是只读    

源码如下:

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

    int getPropagationBehavior();

    int getIsolationLevel();

    int getTimeout();

    boolean isReadOnly();

    String getName();
} 

  2、TransactionStatus:描述事务具体的运行状态,继承了SavepointManager接口

public interface TransactionStatus extends SavepointManager, Flushable {
    boolean isNewTransaction();

    boolean hasSavepoint();

    void setRollbackOnly();

    boolean isRollbackOnly();

    void flush();

    boolean isCompleted();
} 

  

public interface SavepointManager {
    Object createSavepoint() throws TransactionException;

    void rollbackToSavepoint(Object var1) throws TransactionException;

    void releaseSavepoint(Object var1) throws TransactionException;
} 

  

boolean isNewTransaction():判断当前事务是否是一个新事务,如果返回false,说明当前事务已存在,或者该操作没在事务环境中。

boolean hasSavepoint():判断当前事务是否有保存点。

void setRollbackOnly():设置当前事务为rollback-only模式,事务管理器接收到这个指令之后会回滚事务

boolean isRollbackOnly():判断当前事务是否是rollback-only

void flush():用于刷新底层会话的修改到数据库

boolean isCompleted():判断当前事务是否已经结束

Object createSavepoint():创建保存点

void rollbackToSavepoint(Object var1) :使事务回滚到保存点上,回滚之后保存的自动释放

void releaseSavepoint(Object var1) :释放指定保存点

 

  3、PlatFormTransactionManager: 事务管理器

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}

  

TransactionStatus getTransaction(TransactionDefinition var1):事务管理器根据TransactionDefinition描述的事务属性创建一个事务,并返回一个 TransactionStatus用来具体描述事务的运行状态。

 

void commit(TransactionStatus var1):事务管理器根据事务的运行状态对事务进行提交操作,如果该事物被设置为rollback-only,则将事务回滚

 

void rollback(TransactionStatus var1): 事务管理器对事务进行回滚操作。

 

工作中使用Mybatis持久层框架,Mybatis事务管理器的实现类是

org.springframework.jdbc.datasource.DataSourceTransactionManager

需要在spring配置文件进行配置

技术分享

 

3、使用XML配置声明式事务

        Spring使用XML配置声明式事务分为两种,一种用TransactionProxyFactoryBean,一种用aop/tx,由于早期Spring没有aop的特性,所以用代理工厂的方式配置事务,现在这种方式已经很少使用,所以不研究了。下面研究下使用aop/tx,配置事务。

        首先定义一个类。

@Service
@Transactional
public class BbtForum{
    public ForumDao forumDao;
    public TopicDao topicDao;
    public PostDao  postDao;
    public void addTopic(Topic topic){
        topic.addTopic(topic);
        postDao.addPost(topic.getPost());
    }
    public Forum getForum(int forumId){
        return forumDao.getForum(forumId);
    }
    public void updateForum(Forum forum){
        forumDao.updateForum(forum);
    }
    public int getForumNum(){
        return forumDao.getForumNum();
    }
} 

  技术分享技术分享

技术分享

    Spring通过<aop:pointcut>来指定需要织入增强的切点,此处定义的是该包下所有类的所有方法,通过<tx:advice>声明增强,此处需要事务管理器,通过<tx:method>为加入事务的方法指定属性,<tx:method>的属性有name,propagation,isolation,timeout,read-only,rollback-for,non-rollback-for

  

4、使用注解的方式配置事务

        这也是我平时最常用的方式,使用注解配置事务需要先在配置文件中加载注解驱动

 技术分享

  注解驱动配置后,就可以用@Transacational注解来配置事务,该注解有以下属性可以配置:propagation,isolation,read-only,timeout,rollbackFor,noRollbackFor,rollbackForClassName,noRollBackForClassName

  @Transacational注解可以用在类上,代表该类所有的方法都运行在事务环境中,也可以单独配置在方法上,给方法设置特定的事务环境。但是一般不标注在接口或抽象类上,因为@Transacational不能被继承。

技术分享

以上是关于Spring对事务的支持的主要内容,如果未能解决你的问题,请参考以下文章

牛皮,你竟然徒手写出来了Spring事务的核心代码!

Spring对事务的支持

Android:使用支持片段管理器时复制片段

Spring4——对 事务 的支持

事务的学习,从jdbc开始:jdbc对事务的支持与实现

Spring对事务的支持