一、编程式事务
使用原生的JDBC API进行事务管理
[1]获取数据库连接Connection对象
[2]取消事务的自动提交
[3]执行操作
[4]正常完成操作时手动提交事务
[5]执行失败时回滚事务
[6]关闭相关资源
1 1.编程式事务
2 //1.获取Connection对象
3 Connection conn = JDBCUtils.getConnection();
4 try {
5 //2.开启事务:阻止自动提交
6 conn.setAutoCommit(false);
7 //3.执行数据库操作
8 chain.doFilter(req,resp);
9 //4.提交事务
10 conn.commit();
11 }catch(Exception e) {
12 //5.回滚事务
13 conn.rollBack();
14
15 }finally{
16 //6.释放资源
17 }
二、基于注解的声明式事务
1、基本原理:AOP
[1]前置通知:开启事务
[2]返回通知:提交事务
[3]异常通知:回滚事务
[4]后置通知:释放资源
2、事务管理器
DataSourceTransactionManager:配置该类的bean对象,并配置
3、导入jar包
[1]IOC容器需要的jar包
commons-logging-1.1.3.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
[2]AOP需要的jar包
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
[3]JdbcTemplate操作需要的jar包
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
[5]MySQL驱动和C3P0
c3p0-0.9.1.2.jar
mysql-connector-java-5.1.37-bin.jar
4、配置
[1]配置数据源
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.passowrd}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
</bean>
[2]配置JdbcTemplate,并装配数据源
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
[3]配置事务管理器,并装配数据源
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name= "dataSource" ref ="comboPooledDataSource"/>
</bean >
[4]开启基于注解的声明式事务功能
<tx:annotation-driven transaction-manager ="dataSourceTransactionManager"/>
如果事务管理器的bean的id正好是transaction-manager的默认值transactionManager,则可以省略
[5]在事务方法上加@Transactional注解,即可开启该方法的事务
5、事务属性的设置
①事务的传播行为
事务传播属性可以在@Transactional注解的propagation属性中定义。
REQUIRED
REQUIRES_NEW
②事务的隔离级别
用@Transactional注解声明式地管理事务时可以在@Transactional的isolation属性中设置隔离级别
①读未提交:READ UNCOMMITTED
允许Transaction01读取Transaction02未提交的修改。
②读已提交:READ COMMITTED
要求Transaction01只能读取Transaction02已提交的修改。
③可重复读:REPEATABLE READ
确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。
④串行化:SERIALIZABLE
确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。
③事务根据什么异常不进行回滚
@Transactional 注解
[1]rollbackFor属性:指定遇到时必须进行回滚的异常类型,可以为多个
[2]noRollbackFor属性:指定遇到时不回滚的异常类型,可以为多个
④事务的超时属性
@Transactional的timeout属性中设置超时属性
⑤事务的只读属性
@Transactional的readOnly=true属性中设置只读属性,多用于查询操作
三、基于xml的声明式事务
1、配置数据源
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.passowrd}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
</bean>
2、配置JdbcTemplate,并装配数据源
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
3、配置事务管理器,并装配数据源
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name= "dataSource" ref ="comboPooledDataSource"/>
</bean >
4、配置切入点表达式
通过<aop:config></aop:config>标签
配置切入点表达式<aop:pointcut></aop:pointcut>
通过<aop:advisor></aop:advisor>标签将事务与切入点表达式联系起来,明确事务作用的对象
5、配置事务
通过<tx:advice></tx:advice>标签的 transaction-manager属性将当前事物加入到事务管理器
通过<tx:attributes></tx:attributes>标签下的<tx:method></tx:method>标签,配置事务作用范围内的方法的传播行为、隔离级别、异常回滚、超时属性和只读属性
6、详细步骤:
<!-- 配置基于XML文件的声明式事务 -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut expression="execution(* com.neuedu.tx.service.BookService.*(String, String))" id="txPointCut"/>
<!-- 将事务切入点和事务建议的配置联系起来 -->
<aop:advisor advice-ref="bookTransaction" pointcut-ref="txPointCut"/>
</aop:config>
<!-- 设置事务属性 -->
<tx:advice id="bookTransaction" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<tx:method name="doCash"
propagation="REQUIRED"
isolation="READ_COMMITTED"
read-only="false"
no-rollback-for="java.lang.ArithmeticException"
timeout="3" />
<!-- 将某一类方法统一设置为只读 -->
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
</tx:attributes>
</tx:advice>