Spring(八)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不能被继承。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值