文章目录
SpringAOP声明式事务基础
事务管理器
Spring在jdbc中提供了一个事务管理组件:
PlatformTransactionManager
- DataSourceTransactionManager
声明式事务配置的两种基本方式:
XML配置方式
准备阶段:通过xml配置声明式事务,我们需要添加tx命名空间
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
准备阶段:通过xml方式配置Spring声明式事务
<context:component-scan base-package="com.lanou3g.spring.transaction"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="teacherDao" class="com.lanou3g.spring.transaction.dao.TeacherDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
xml配置开始:
第一步:配置数据源
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="connectionProperties">
<props>
<prop key="characterEncoding">${jdbc.characterEncoding}</prop>
</props>
</property>
</bean>
第二步:初始化事务管理器
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
第三步::配置事务AOP通知
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="insert*" rollback-for="ArithmeticException"/>
<tx:method name="query*" read-only="true" isolation="READ_UNCOMMITTED"/>
</tx:attributes>
</tx:advice>
第四步:定义AOP配置(将上面的通知和表达式组装到一起)
<aop:config>
<aop:pointcut id="all_dao_method" expression="execution(* com.lanou3g.spring.transaction.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="all_dao_method"/>
</aop:config>
配置结束…
注解配置方式
第一步:开启事务注解支持
@Configuration
@EnableTransactionManagement
public class MyTransactionConf {
}
第二步:配置事务管理器
/**
* 通过注解的方式配置Spring声明式事务
*/
@Configuration
public class MyTransactionConf {
/**
* 定义TransactionManager bean
* @param dataSource
* @return
*/
@Bean
public PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
第三步:在需要事务的方法上添加事务注解
// 给批量插入方法添加事务控制
@Transactional
@Override
public int[] batchInsertStudent(List<Student> studentList) {
// 具体操作....
}
@Transactional属性说明
value: 指定特定的事务管理器,默认是transactionManager
其他属性和xml中的的属性类似
Spring事务的传播行为和隔离级别:
七种传播行为:
1. PROPAGATION_REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
2. PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。
3. PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。
4. PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。
5. PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6. PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。
五种隔离级别:
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生
已提交读 (read commited):避免脏读。但是不可重复读和虚读有可能发生
可重复读 (repeatable read) :避免脏读和不可重复读.但是虚读有可能发生.
串行化的 (serializable) :避免以上所有读问题.
Mysql 默认:可重复读
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
Read uncommitted | Y | Y | Y |
Read committed | N | Y | Y |
Repeateble read | N | N | Y |
Serializable | N | N | N |
关键词:
幻读(虚读)
事务1读取记录时事务2增加了记录并提交,事务1再次读取时可以看到事务2新增的记录;
通俗的说,幻读就是指在一个事务内读取了别的事务插入的数据,导致前后读取不一致(insert)
不可重复读取
事务1读取记录时,事务2更新了记录并提交,事务1再次读取时可以看到事务2修改后的记录;
在一个事务内读取表中的某一行数据,多次读取结果不同.一个事务读取到了另一个事务提交后的数据.
脏读
事务1更新了记录,但没有提交,事务2读取了更新后的行,然后事务T1回滚,现在T2读取无效。
通俗的说,脏读就是指一个事务读取了一个未提交事务的数据
回滚事务:
回滚特定异常
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
不回滚特定异常
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>