事务
事务特性:acid
事务并发问题
脏读
不可重复读
幻读
事务的隔离级别
1 读未提交
2 读已提交
4 可重复读
8 串行化
spring封装了事务管理代码
事务操作
打开事务
提交事务
回滚事务
事务操作对象
因为在不同平台,操作事务的代码各不相同.spring提供了一个接口
DataSourceTransactionManager
HibernateTransitionmanager
注意:在spring中玩事务管理.最为核心的对象就是TransactionManager对象
spring管理事务的属性介绍
事务的隔离级别
1 读未提交
2 读已提交
4 可重复读
8 串行化
是否只读
true 只读 false 可操作
事务的传播行为
* 保证同一个事务中
PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
* 保证没有在同一个事务中
PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
spring管理事务方式
编码式(观光代码)
1.将核心事务管理器配置到spring容器
<bean name ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name ="dataSource" ref ="dataSource" > </property >
</bean >
2.配置TransactionTemplate模板
<bean name ="transactionTemplate" class ="org.springframework.transaction.support.TransactionTemplate" >
<property name ="transactionManager" ref ="transactionManager" > </property >
</bean >
3.将事务模板注入Service
<bean name ="dataSource" class ="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name ="jdbcUrl" value ="${jdbc.jdbcUrl}" > </property >
<property name ="driverClass" value ="${jdbc.driverClass}" > </property >
<property name ="user" value ="${jdbc.user}" > </property >
<property name ="password" value ="${jdbc.password}" > </property >
</bean >
<bean name ="accountDao" class ="cn.zdfy.dao.AccountDaoImpl" >
<property name ="dataSource" ref ="dataSource" > </property >
</bean >
<bean name ="accountService" class ="cn.zdfy.service.AccountServiceImpl" >
<property name ="ad" ref ="accountDao" > </property >
<property name ="tt" ref ="transactionTemplate" > </property >
</bean >
4.在Service中调用模板
public void transfer (final Integer from, final Integer to, final Double money) {
tt.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult (TransactionStatus arg0) {
ad.decreaseMoney(from, money);
int i = 1 / 0 ;
ad.increaseMoney(to, money);
}
});
}
xml配置(aop)
1.导包
2.导入新的约束(tx)
beans: 最基本
context: 读取properties配置
aop: 配置aop
tx: 配置事务通知
3.配置通知
<tx:advice id ="txAdvice" transaction-manager ="transactionManager" >
<tx:attributes >
<tx:method name ="save*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="false" />
<tx:method name ="persist*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="false" />
<tx:method name ="update*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="false" />
<tx:method name ="modify*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="false" />
<tx:method name ="delete*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="false" />
<tx:method name ="remove*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="false" />
<tx:method name ="get*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="true" />
<tx:method name ="find*" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="true" />
<tx:method name ="transfer" isolation ="REPEATABLE_READ" propagation ="REQUIRED" read-only ="false" />
</tx:attributes >
</tx:advice >
4.配置将通知织入目标
<aop:config >
<aop:pointcut expression ="execution(* cn.zdfy.service.*ServiceImpl.*(..))" id ="txPc" />
<aop:advisor advice-ref ="txAdvice" pointcut-ref ="txPc" />
</aop:config >
注解配置(aop)
1.导包
2.导入新的约束(tx)
beans: 最基本
context: 读取properties配置
aop: 配置aop
tx: 配置事务通知
3.开启注解管理事务
<tx:annotation-driven />
4.使用注解
@Transactional (isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true )
public class AccountServiceImpl implements AccountService {
@Transactional (isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false )
public void transfer (final Integer from, final Integer to, final Double money) {