spring 事务
事务的概念
事务指数据库中多个操作合并在一起形成的操作序列
事务的隔离级
-
脏读:允许读取未提交的信息
原因:Read uncommitted 解决方案: (表级读锁)
-
不可重复读:读取过程中单个数据发生了变化
解决方案: Repeatable read (行级写锁)
-
幻读:读取过程中数据条目发生了变化
解决方案: Serializable(表级写锁)
事务管理
Spring事务核心对象
spring为业务层提供了整套的事务解决方案
-
PlatformTransactionManager
-
TransactionDefinition
-
TransactionStatus
PlatformTransactionManager平台事务管理器实现类
-
DataSourceTransactionManager 适用于Spring JDBC或MyBatis
-
HibernateTransactionManager 适用于Hibernate3.0及以上版本
-
JpaTransactionManager 适用于JPA
-
JdoTransactionManager 适用于JDO
-
JtaTransactionManager 适用于JTA
常用方法:获取事务 :TransactionStatus getTransaction(TransactionDefinition definition) 提交事务 :void commit(TransactionStatus status) 回滚事务 :void rollback(TransactionStatus status)
TransactionDefinition
获取事务定义名称:String getName()
获取事务的读写属性:boolean isReadOnly()
获取事务隔离级别:int getIsolationLevel()
获事务超时时间:int getTimeout()
获取事务传播行为特征:int getPropagationBehavior()
TransactionStatus
获取事务是否处于新开启务状态:boolean iaNewTransaction()
刷新事务状态:void flush()
获取事务是否处于已完成状态:boolean iaCompleted()
获取事务是否具有回滚存情点:boolean hasSavepoint ()
获取事务是否处于回滚状态:boolean isRollbackOnly()
设置事务处于回滚状态:void setRollbackOnly()
编程式事务
public void transfer(String outName,String inName,Double money){
//创建事务管理器
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
//为事务管理器设置与数据层相同的数据源
dstm.setDataSource(dataSource);
//创建事务定义对象
TransactionDefinition td = new DefaultTransactionDefinition();
//创建事务状态对象,用于控制事务执行
TransactionStatus ts = dstm.getTransaction(td);
accountDao.inMoney(outName,money);
int i = 1/0; //模拟业务层事务过程中出现错误
accountDao.outMoney(inName,money);
//提交事务
dstm.commit(ts);
}
使用AOP控制事务
将业务层的事务处理功能抽取出来制作成AOP通知,利用环绕通知运行期动态织入
public Object tx(ProceedingJoinPoint pjp) throws Throwable {
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
TransactionDefinition td = new DefaultTransactionDefinition();
TransactionStatus ts = dstm.getTransaction(td);
Object ret = pjp.proceed(pjp.getArgs());
dstm.commit(ts);
return ret;
}
配置AOP通知类,并注入dataSource
<bean id="txAdvice" class="com.itheima.aop.TxAdvice">
<property name="dataSource" ref="dataSource"/>
</bean>
使用环绕通知将通知类织入到原始业务对象执行过程中
<aop:config>
<aop:pointcut id="pt" expression="execution(* *..transfer(..))"/>
<aop:aspect ref="txAdvice">
<aop:around method="tx" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
声明式事务(XML)
public Object tx(ProceedingJoinPoint pjp) throws Throwable {
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
TransactionDefinition td = new DefaultTransactionDefinition();
TransactionStatus ts = dstm.getTransaction(td);
Object ret = pjp.proceed(pjp.getArgs());
dstm.commit(ts);
return ret;
}
<bean id="txAdvice" class="com.itheima.aop.TxAdvice">
<property name="dataSource" ref="dataSource"/>
</bean>
使用tx命名空间配置事务专属通知类
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="*" propagation="NOT_SUPPORTED" read-only="true"/>
</tx:attributes>
</tx:advice>
使用aop:advisor在AOP配置中引用事务专属通知类
<!--4、配置aop管理切入点和通知-->
<aop:config>
<!--定义切面,表达式匹配所有的连接点方法-->
<aop:pointcut id="pointcut" expression="execution(* com.entor.jdbc.service.impl.*.*(..))"/>
<!--把切面和通知关联上-->
<aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>
</aop:config>
aop:advice与aop:advisor区别
aop:advice配置的通知类可以是普通java对象,不实现接口,也不使用继承关系
aop:advisor配置的通知类必须实现通知接口
MethodBeforeAdvice
AfterReturningAdvice
ThrowsAdvice
tx:advice
类型:标签
归属:beans标签
作用:专用于声明事务通知
基本属性:
id :用于配置aop时指定通知器的id
transaction-manager :指定事务管理器bean
tx:attributes
类型:标签
归属:tx:advice标签
作用:定义通知属性
tx:method
类型:标签
归属:tx:attribute标签
作用:设置具体的事务属性
说明:通常事务属性会配置多个,包含1个读写的全事务属性,1个只读的查询类事务属性
tx:method属性
声明式事务(注解)
@Transactional
类型:方法注解,类注解,接口注解
位置:方法定义上方,类定义上方,接口定义上方
作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性
@Transactional//等价于<tx:annotation-driven transaction-manager="txManager"/>
(
readOnly = false,
timeout = -1,
isolation = Isolation.DEFAULT,
rollbackFor = {ArithmeticException.class, IOException.class},
noRollbackFor = {},
propagation = Propagation.REQUIRES_NEW
)
tx:annotation-driven
类型:标签
归属:beans标签
作用:开启事务注解驱动,并指定对应的事务管理器
<tx:annotation-driven transaction-manager="txManager"/>
声明式事务(纯注解驱动)
@EnableTransactionManagement
类型:类注解
位置:Spring注解配置类上方
作用:开启注解驱动,等同XML格式中的注解驱动
@Configuration
@ComponentScan("com.entor")
@PropertySource("classpath:jdbc.properties")
@Import({JDBCConfig.class,MyBatisConfig.class,TransactionManagerConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}
public class TransactionManagerConfig {
@Bean
public PlatformTransactionManager getTransactionManager(@Autowired DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
@Bean("dataSource")
public DruidDataSource getDataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
ds.setUrl("jdbc:oracle:thin:@localhost:1521:XE");
ds.setUsername("jsd2101");
ds.setPassword("jsd2101");
return ds;
}
@Bean
public DataSourceTransactionManager getTransactionManager(DruidDataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
@Bean
public JdbcTemplate getJDBCTemplate(DruidDataSource dataSource){
return new JdbcTemplate(dataSource);
}