事务相关的知识

事务的特性:

原子性:事务是不可分割的最小单元,事务里的操作要么都做要么都不做

隔离性:在并发程序中,并发事务之间互不影响,在对一个事务的操作不会对其他事务产生影响,事务的隔离性需要事务的隔离级别来完成。

一致性:在事务执行前后数据库的数据都处于正确的状态,

持久性:事务一旦执行成功,那么对数据库数据的改变是永久的,不会因为因为断点或者系统故障而发生数据丢失。

 

在实际项目开发中,事务一般都是并发执行的,事务并发执行一般会遇到以下问题:

丢失更新:两个事务先后更新同一行数据,后执行的事务的更新覆盖掉了前一个事务的更新,这样会导致前一个事务更新的数据丢失,这是由于没有加锁造成的。

脏读:一个事务看到了另一个事务未提交的更新的数据。

不可重复读:在同一事物中,多次读取同一条数据确返回不同的结果。因为有其他的事务更改了这些数据。

幻读:一个事务在执行过程中读取到了另一个事务已提交的插入数据,即第一个事务开始时读取到一批数据,此时另一个事务又插入数据并提交,然后第一个事务又读取这批数据单发现多了一条。

 

为了解决事务并发的问题,规定了四种隔离级别:

1.未提交读:最低的隔离级别,一个事务能够读取到别的事务未提交的更新数据,这很不安全,可能会导致丢失更新,脏读,不可重复读,幻读。

2.提交读:一个事务能读取到别的事务提交的更新数据,不能看到未提交的更新数据,这样避免了丢失更新,但是肯能会产生脏读、不可重复读、幻读。

3.可重复读:保证同一个事务中先后执行多次查询都返回同一个结果,不受其他事务的影响,解决了丢失更新、脏读、不可重复读的问题,但是可能产生幻读。

4.序列化:最高隔离级别,不允许事务并发执行,只能串行执行,避免了,丢失更新、脏读、不可重复读、幻读等问题。

 

spring中对事务的支持分为物理事物和逻辑事务。

物理事物就是底层数据库提供的事务支持,例如JDBC

逻辑事务是spring管理的事务,逻辑事务提供更丰富的控制,在spring中如果没有强调一般就是逻辑事务。

 

DefaultTransactionDefinition:事务定义,定义如隔离级别、传播行为,事务超时时间,事务是否只读等。

 

例如:

  1.  DefaultTransactionDefinition def = new DefaultTransactionDefinition();  
  2.     def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
  3.     def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 

 

定义事务的隔离级别为提交读,传播行为为必须有事务,如果没有事务则创建一个事务。

TransactionStatus:表示事务的状态,获取事务状态后,spring根据事务的传播行为开启事务。

 

事务隔离级别

spring 中使用TransactionDefinition的静态变量来制定事务的隔离级别:

ISOLATION_DEFAULT:默认的隔离级别,使用底层的数据库的默认的隔离级别。

IOSLATION_READ_UNCOMMITED:未提交读

ISOLATION_READ_COMMITED:提交读

IOSLATION_REPEATABLE_READ:可重复读

IOSLATION_SERIALIZABLE:序列化

 

事务的传播行为:

事务的传播行为指定在多个事务方法间调用时,事务是如何在这些方法间传播的。

spring共支持7种事务传播行为:

1.reuqired:必须有事务,否则新建一个事务,使用PROPAGATION_REQUIRED指定。

2.requiresNew:表示每次都创建新的逻辑事务,使用PROPAGATION_REQUIRES_NEW指定。

3.Supports:支持当前事务,使用PROPAGATION_SUPPORTS指定,如果当前存在逻辑事务,就加入到该逻辑事务中,如果当前没有逻辑事务就以非逻辑事务的方式运行。

4.NotSupported:不支持事务,如果当前存在事务,则暂停该事物,以非事务的方式运行,使用PROPAGATION_NOT_SUPPORTED指定

5.Mandatory:使用当前事务执行,如果当前没有事务则抛出异常,用PROPAGATION_MANDATORY指定

6.NEVER:不支持事务,如果当前存在事务则抛出异常,使用PROGATION_NEVER指定。

7.NESTED:嵌套事务支持,如果当前存在事务,则在嵌套事务内执行,如果当前事务不存在,则创建新的事务。嵌套事务使用数据库中的保存点来执行,即嵌套事务回滚将不影响外部事务,外部事务回滚将导致嵌套事务回滚。

 

  1. <tx:advice id="txAdvice" transaction-manager="txManager">  
  2. <tx:attributes>  
  3.            <tx:method name="save*" propagation="REQUIRED" />  
  4.            <tx:method name="add*" propagation="REQUIRED" />  
  5.            <tx:method name="create*" propagation="REQUIRED" />  
  6.            <tx:method name="insert*" propagation="REQUIRED" />  
  7.            <tx:method name="update*" propagation="REQUIRED" />  
  8.            <tx:method name="merge*" propagation="REQUIRED" />  
  9.            <tx:method name="del*" propagation="REQUIRED" />  
  10.            <tx:method name="remove*" propagation="REQUIRED" />  
  11.            <tx:method name="put*" propagation="REQUIRED" />  
  12.            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />  
  13.            <tx:method name="count*" propagation="SUPPORTS" read-only="true" />  
  14.           <tx:method name="find*" propagation="SUPPORTS" read-only="true" />  
  15.           <tx:method name="list*" propagation="SUPPORTS" read-only="true" />  
  16.           <tx:method name="*" propagation="SUPPORTS" read-only="true" />  
  17.        </tx:attributes>  
  18. </tx:advice>  

 

 

 注解式事务声明:

 

  @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED)

    @Override

    public void save(final UserModel user) {

        userDao.save(user);

        user.getAddress().setUserId(user.getId());

        addressService.save(user.getAddress());

        

    }

    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=true)

    @Override

    public int countAll() {

        return userDao.countAll();

    }

 

 

 

 

猜你喜欢

转载自350083890.iteye.com/blog/2274792
今日推荐