你的位置:首页 > Java教程

[Java教程]Spring in action读书笔记


在软件开发领域,全有全无的操作被称为事务

 

事务的四个特性(ACID

  • 原子性(Atomtic):事务是由一个或多个活动所组成的一个工作单元,要么全部发生,要么全部不发生。
  • 一致性(Consistent):一旦事务完成,系统应确保它所建的业务处于一致的状态。
  • 隔离性(Isolated):事务允许多个用户操作同样的数据,但不能相互影响。
  • 持久性(Durable):事务的结果应该存到数据库或者其他形式的持久化存储中。

spring对事务管理的支持:

  • 编码式:允许用户在代码中精确定义事务的边界
  • 声明式:有助于用户将操作与事务规则进行解耦

 

spring的事务管理器:

 

事务管理器(org.framework.*)

使用场景

 

 

Jdbc.datasource.DataSourceTransactionManager

用于Spring对JDBC抽象的支持,也可用于使用ibatis进行持久化场景

 

 

 

 

 

 

 

 

 

 


 

1 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">2     <property name="dataSource" ref="datasource" />3 </bean>

 

声明事务的三种方式:

  • 使用SpringAOP和TransactionProxyFactoryBean的代理Bean来实现
  • Spring的tx命名空间
  • @Transactional注解

 

事务属性描述了事务策略如何应用到方法上,具体属性如下:

1. 传播行为:定义了客户端与被调用方法之间的事务边界。(P155,表6.2)

传播行为

含义

PROPAGATION_MANADATORY

表示该方法必须在事务中运行,如果当前事务不存在,在会抛出异常

PROPAGATION_NESTED

如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为和

PROPAGATION_NEVER

表示当前方法不应该运行在事务上下文中,如果当前正有一个事务在运行,则会抛出异常

PROPAGATION_NOT_SUPPORTED

表示该方法不应该运行在事务中,如果存在当前事务,在方法运行期间,当前事务将被挂起。

PROPAGATION_REQUIRED

表示当前方法必须运行在事务中,如果当前事务存在方法将会在该事务中运行,否则,会启动一个新的事务。

PROPAGATION_REQUIRES_NEW

表示当前方法必须运行在它自己的事务中,一个新的事务将被启动。如果存在当前事务,该方法执行期间,当前事务会被挂起。

PROPAGATION_SUPPORTS

表示当前方法不需要事务上下文,但如果存在当前事务的话,那么该方法会在这个事务中运行,但并不要求必须在事务中运行。


 

2. 隔离级别:定义了一个事务可能受其他并发事务影响的程度。

事务并发可能导致的问题:

  • 脏读:事务T1读取了事务T2改些后还未提交的数据,T1读取的数据是无效的。
  • 不可重复读:事务T1在查询时,事务T2更新了数据,事务T1再查询时与第一次查询数据不一致了。
  • 幻读:事务T1读取了事务T2插入的一些数据

 

一般情况下事务是完全隔离的,但完全隔离影响性能,因此需要事务隔离级别来增加事务的灵活性。

隔离级别

含义

ISOLATION_DEFAULT

使用后端数据库默认的隔离级别

ISOLATION_READ_UNCOMMITTED

允许读取尚未提交的数据变更,可能会导致脏读,幻读或不可重复读

ISOLATION_READ_COMMITTED

允许读取并发事务已经提交的数据,可以阻止脏读,但幻读和不可重复读仍可能发生

ISOLATION_REPEATABLE_READ

对同一字段的多次读取结果是一致的,除非数据是被本事务自己所修改。可以阻止脏读和不可重复读写,但幻读仍可能发生

ISOLATION_SERIALIZABLE

完全服从ACID的隔离级别,完全锁定相关事务,性能较低


 

3. 只读:数据库可以利用事务的只读特性来进行一些特定的优化

 

4. 事务超时:事务可能涉及对后端数据库的锁定,事务时间过长会占用数据库资源,需指定超时时间自动回滚。

 

5. 回滚规则:默认情况下事务只有在遇到运行时异常才会回滚,你也可以设置在遇到检查型异常时也回滚,或者运行时异常不回滚。

 

在中定义事务

  • 早期:声明事务需要装配一个名为TransactionProxyFactoryBean的特殊bean
  • 现在:使用tx命名空间会将其添加到Spring配置文件中(P158),一些声明式事务配置元素依赖于部分spring的AOP配置元素,aop命名空间也应该包括在内。

 

 1 <tx:advice id = "txAdvice"> 2  3 <tx:attributes> 4  5 <tx:method name="save*" propagation = "REQUIRED" /> 6  7 <tx:method name ="*" propagation="SUPPORTS" read-only = "true"/> 8  9 </tx:attributes>10 11 </tx:advice>

tx配置

<tx:method> 有多个属性来帮助定义方法的事务策略:

隔离级别

含义

isolation

指定事务的隔离级别

propagation

定义事务的传播规则

read-only

指定事务为只读

回滚规则:

rollbak-for

no-rollback-for

指定事务对于那些检查型异常应当回滚而不提交

指定事务对于那些异常应当继续运行而不回滚

timeout

对于长时间运行的事务定义超时时间


 

定义注解驱动的事务

使用注解的方式只需配置一行:<tx : annotation-driven />,它会告诉Spring检查上下文中所有使用@Transactional注解的Bean,自动为它们添加事务通知,通知的属性是通过@Transactional注解的参数来定义的:

@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)  public void addAndUpdateOrders(List<InvoiceOrderApi> invoiceOrderApis, List<InvoiceOrder> invoiceOrders, InvoiceApply apply){  ...}

 

也可以配置指定特定的事务管理器:<tx : annotation-driven transaction-manager = "txManager"/>