spring的早期版本用户必须通过TransactionProxyFactoryBean代理对需要事务管理的业务类进行代理,便于实施事务功能的增强。
让我们先看代码吧!
Spring处理模块是通过AOP实现声明式事务处理的,有一种老的方式就是通过TransactionProxyFactoryBean生成一个代理对象,然后调用监听器来完成对代理方法的拦截。
Spring配置文件:
- <!-- 定义一个数据源 -->
- <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver" />
- <property name="url" value="jdbc:mysql://localhost:3306/spring_test" />
- <property name="username" value="root" />
- <property name="password" value="root" />
- </bean>
- <!-- 定义JdbcTemplate的Bean -->
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
- p:dataSource-ref="dataSource">
- </bean>
- <bean id="userScoreRepository_jdbc"
- class="net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl"
- p:jdbcTemplate-ref="jdbcTemplate" />
- <!-- 声明事务管理器 -->
- <bean id="txManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <!-- 需要实施事务增强的目标业务Bean -->
- <bean id="userScoreTarget"
- class="net.hingyi.springDemo.transaction.service.UserScoreServiceImpl"
- p:userScoreRepository-ref="userScoreRepository_jdbc" />
- <!-- 使用事务代理工厂类为目标业务Bean提供事务增强 -->
- <!-- p:transactionManager-ref="txManager" 指定事务管理器 -->
- <!-- p:target-ref="userScoreTarget" 指定目标业务Bean -->
- <bean id="userScore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
- p:transactionManager-ref="txManager"
- p:target-ref="userScoreTarget">
- <property name="transactionAttributes">
- <props>
- <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <!-- 只读事务 -->
- <prop key="*">PROPAGATION_REQUIRED</prop> <!-- 可写事务 -->
- </props>
- </property>
- </bean>
<!-- 定义一个数据源 -->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/spring_test" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- 定义JdbcTemplate的Bean -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource">
</bean>
<bean id="userScoreRepository_jdbc"
class="net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl"
p:jdbcTemplate-ref="jdbcTemplate" />
<!-- 声明事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 需要实施事务增强的目标业务Bean -->
<bean id="userScoreTarget"
class="net.hingyi.springDemo.transaction.service.UserScoreServiceImpl"
p:userScoreRepository-ref="userScoreRepository_jdbc" />
<!-- 使用事务代理工厂类为目标业务Bean提供事务增强 -->
<!-- p:transactionManager-ref="txManager" 指定事务管理器 -->
<!-- p:target-ref="userScoreTarget" 指定目标业务Bean -->
<bean id="userScore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
p:transactionManager-ref="txManager"
p:target-ref="userScoreTarget">
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <!-- 只读事务 -->
<prop key="*">PROPAGATION_REQUIRED</prop> <!-- 可写事务 -->
</props>
</property>
</bean>
异常回滚/提交规则
上面spring配置中的<prop>内的值为事务属性信息,匹配格式为:
PROPAGATION (传播行为) | , | ISOLATION (隔离级别(可选)) | , | readOnly (是否为只读事务(可选)) | , | -Exceptions (发生这些异常时回滚事务(可选))
| , | +Exceptions (发生这些异常时照样提交事务(可选)) |
Spring事务的传播类型
Spring在TransactionProxyFactory接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务发生嵌套调用时候是怎么传播的。如:
事务传播行为类型 | 说明 |
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务;如果已经存在一个事务,加入到这个事务中。(这个是最常见的选择) |
PROPAGATION_SUPPORTS | 支持当前事务。如果当前没有事务,就以非事务方式执行 |
PROPAGATION_MANDATORY | 使用当前的事务。如果当前没有事务,就抛出异常 |
PROPAGATION_REQUIRES_NEW | 新建事务。如果当前存在事务,就把当前事务挂起 |
PROPAGATION_NOT_SUPPORTED | 以非事务的方式执行操作。如果当前存在事务,就把当前事务挂起 |
PROPAGATION_NEVER | 以非事务方式执行。如果当前存在事务,则抛出异常 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED类似的操作 |
隔离级别
隔离级别是可选的,默认的为ISOLATION_DEFAULT,表示数据库的默认隔离级别。隔离级别的值如下:
隔离级别 | 脏读 | 不可重复读 | 幻象读 | 第一类丢失更新 | 第二类丢失更新 |
ISOLATION_READ_UNCOMMITED | 允许 | 允许 | 允许 | 不允许 | 允许 |
ISOLATION_READ_COMMITED | 不允许 | 允许 | 允许 | 不允许 | 允许 |
ISOLATION_REPEATABLE_READ | 不允许 | 不允许 | 允许 | 不允许 | 不允许 |
ISOLATION_SERIALIZABLE | 不允许 | 不允许 | 不允许 | 不允许 | 不允许 |
默认情况下,当发生运行异常时,事务将被回滚,发生检查型异常时,既不回滚也不提交,控制权交给外层调用。所以,带负号的异常设置仅对检查型异常有意义。