65 lines
8.0 KiB
Markdown
65 lines
8.0 KiB
Markdown
# Spring Data Access
|
||
- ## Spring事务
|
||
- 本地事务和全局事务:
|
||
- 全局事务:全局事务允许使用多个事务资源,应用服务器来对全局事务进行管理
|
||
- 本地事务:本地事务无法管理多个事务资源
|
||
- 本地事务和全局事务的优缺点
|
||
- 全局事务的使用需要和服务器环境相绑定,降低了代码的重用性
|
||
- 本地事务无法使用多个事务资源,无法通过JTA等框架来对多个事务资源进行管理,无法使用分布式事务
|
||
- ## 声明式事务
|
||
- Spring中声明式事务是通过AOP来实现的
|
||
- 在声明式事务中,可以为方法级的粒度指定事务行为
|
||
- 声明式事务的回滚规则:
|
||
- 在Spring声明式事务中,可以为事务指定回滚规则,即指定针对哪些异常,事务会自动执行回滚操作
|
||
- 在默认情况下,只有抛出unchecked异常(通常为RuntimeException)时,声明式事务才会进行回滚
|
||
- 声明式事务的实现细节:
|
||
- 声明式事务通过aop代理实现,并且事务的advice是通过xml元数据配置来驱动的
|
||
- aop和事务元数据联合产生了一个aop代理对象,并且该代理对象通过使用TransactionInterceptor和TransactionManager来实现事务
|
||
- @Transactional通常和线程绑定的事务一起工作,线程绑定的事务由PlatformTransactionManager管理。@Transactional会将事务暴露给当前执行线程中所有的dao操作
|
||
- 声明式事务的回滚:
|
||
- 在Spring事务中推荐让事务回滚的方式是在事务执行的方法中抛出一个异常
|
||
- Spring事务在默认情况下只会针对unchecked异常(RuntimeException)进行回滚,对于Error,Spring事务也会执行回滚操作
|
||
- checked异常并不会导致事务的回滚操作,可以注册rollback rule来指定对特定的异常(包括checked异常)进行回滚操作
|
||
- rollback rule:
|
||
- 回滚规则(rollback rule)通常用来指定当一个异常被抛出时,是否为该异常执行事务的回滚操作
|
||
- 在@Transactional注解中,可以指定rollbackFor/noRollbackFor、rollbackForClassName/noRollbackForClassName来指定为那些异常类执行回滚操作
|
||
```java
|
||
@Transactional(rollbackFor={MyException.class})
|
||
public void myOperation() {
|
||
// ...
|
||
}
|
||
```
|
||
- ## 基于注解的声明式事务
|
||
- @Transactional既可以作用于类上,也可以作用于方法上。当作用于类上时,该声明类中所有的方法都会被声明是事务的,该类子类中所有的方法也都是事务的
|
||
- @Transactional是可以继承的,被@Inherited元注解修饰。
|
||
>@Inherited类是元注解,用来修饰注解类。如果一个注解类被@Inherited注解标识,那么在对class查询该注解类时,如果当前class没有声明该注解,将会在当前class的父类中查找该注解,依次递归。直到在父类中找到该注解或是到达继承结构的顶部(Object类)。@Inherited标注的注解仅能在类继承中有效,如注解被标注在接口上,那么将@Inherited标注的注解将不会被递归查询到。
|
||
- 并且,class级别的@Transactional并不应用在从父类继承的方法上,即若一个类被@Transactional注解标注,并且该类从父类继承方法,那么该类从父类继承的方法并不会被看作是事务的,除非在该类中重新声明继承的方法。
|
||
- 通过在Configuration类上注解@EnableTransactionManagement,配合@Transactional可以将一个bean对象声明是事务的
|
||
- 当基于标准spring配置时,应该仅将@Transactional注解标注于public方法,当将@Transactional注解标注于非public方法时无效
|
||
- 在Spring中,仅推荐将@Transactional注解应用于类上,不推荐将其应用在接口(接口方法)上。如果将其应用在接口上,那么该事务配置仅仅对基于接口的动态代理有效,对基于class的代理无效。
|
||
- 当类级别和方法级别都设置了@Transactional注解时,方法级别的设置会优先被使用
|
||
- ## @Transactional注解的配置
|
||
- 事务的传播: 默认情况下,@Transactional的propagation属性是PROPAGATION_REQUIRED
|
||
- 事务的隔离级别: 默认情况下,@Transactional的isolation属性是ISOLATION_DEFAULT,使用数据库默认的隔离级别
|
||
- readOnly: 默认情况下,@Transactional的readOnly属性是false,默认事务是可读写的
|
||
- timeout: 默认况下下,@Transactional的超时属性取决于底层的事务系统,如果底层事务系统不支持timeout,则timeout属性为none
|
||
- rollbackFor: 默认情况下,@Transactional会针对unchecked异常和Error进行回滚操作
|
||
- transactionManager: 默认情况下,@Transactional注解会使用项目中默认的事务管理器(即bean name为transactionManager的事务管理器)。可以为@Transactional注解指定value属性或是transactionManager属性来指定想要采用的事务管理器的bean name或是qualifier
|
||
- ## Transaction Propagation
|
||
- ### PROPAGATION_REQUIRED
|
||
- 在Spring中,事务的传播行为默认是PROPAGATION_REQUIRED,默认情况下该选项会强制的要求一个物理事务
|
||
- 如果当前作用域中不存在事务,那么会创建一个新的事务
|
||
- 如果当前作用域的外层作用域已经存在事务,那么会加入到当前作用域的事务中去
|
||
- 在Spring中,默认情况下,当嵌套事务加入到外层的事务中时,会忽略内层事务定义的隔离级别、timeout设置和读写标志等。
|
||
> 如果想要对外层事务进行验证,可以手动将事务管理器的validateExistingTransaction属性设置为true。这样,当加入到一个隔离级别与内层事务完全不同的外层事务中时,该加入操作会被拒绝。在该设置下,如果read-write内层事务想要加入到外层的read-only事务中时,该加入操作也会被拒绝。
|
||
- 在事务传播行为被设置为PROPAGATION_REQUIRED的情况下,会为每个被设置事务的方法创建一个逻辑的事务作用域。各个逻辑事务作用域之间都是相互独立的,在不同逻辑事务作用域之间都可以独立设置事务的rollback-only属性。但是,在PROPAGATION_REQUIRED的情况下,内层事务和外层事务都映射到同一个物理事务,内层事务加入到外层事务中,故而在内层逻辑事务中为物理事务设置rollback-only会切实影响到外层事务的提交。
|
||
- 当事务传播行为被设置为PROPAGATION_REQUIRED时,如果内层事务设置了rollback-only标记,那么会导致外层物理事务的回滚。当外层事务尝试提交并失败回滚后,会抛出一个UnexceptedRollbackException异常,外层事务commit方法的调用者会接受到该UnexceptedRollbackException,代表内层发生了非预期的回滚操作
|
||
- ### PROPAGATION_NEW
|
||
- 相对于PROPAGATION_REQUIRED,PROPAGATION_NEW传播行为会一直使用独立的物理事务,而不会尝试区加入外部已经存在的物理事务。
|
||
- 对于PROPAGATION_NEW,其内层事务和外层事务都可以独立的提交或回滚,内层事务的回滚并不会导致外层事务的回滚。
|
||
- 将事务传播行为设置为PROPAGATION_NEW时,内层事务可以独立定义自己的隔离级别、timeout值、read-only属性,而不必继承外部事务的这些属性。在PROPAGATION_REQUIRED中,内部事务自定义这些属性将会被忽略,内部事务加入外部事务后会采用外部事务的设置。
|
||
- ### PROPAGATION_NESTED
|
||
- 和PROPAGATION_REQUIRED类似,PROPAGATION_NESTED同样也只有一个物理事务。但是其支持多个savepoint(存档点),该物理事务可以回滚到特定的存档点而非必须回滚整个事务。
|
||
- 由于PROPAGATION_NESTED对存档点的支持,故而在PROPAGATION_NESTED条件下,可以进行部分回滚。内层事务的回滚操作并不会造成外部事务的回滚,内层事务回滚后外层事务仍然能够继续执行和提交。
|
||
> 由于PROPAGATION_NESTED需要JDBC savepoint(存档点)的支持,故而该设置仅仅对JDBC事务资源有效。
|