一、Spring的事务抽象
一致的事务模型
- 使用JDBC/Mybatis/Hibernate来操作数据库
- 使用DataSource/JTA来操作事务
例如:
PlatformTransactionManager 接口
- DataSourceTransactionManager DataSource
- HibernateTransactionManager Hibernate
- JtaTransactionManager JTA
TransactionDefinition
- Propagation
- Isolation
- Timeout
- Read-only Status
1. 事务传播特性(Spring的)
事务传播特性
传播性 | 值 | 描述 |
---|---|---|
PROPAGATION_REQUIRED | 0 | 默认,当前有事务就沿用,没有就开启新的事务 |
PROPAGATION_SUPPORTS | 1 | 事务可有可无,当前有事务就沿用,没有就不用事务 |
PROPAGATION_MANDATORY | 2 | 当前必须有事务,否则会抛异常 |
PROPAGATION_REQUIRES_NEW | 3 | 开启新的事务,若当前已经有事务则挂起当前事务再开启新事务,新事物执行完则提交,再执行原事务 |
PROPAGATION_NOT_SUPPORTED | 4 | 不支持事务,按非事务方式处理 |
PROPAGATION_NEVER | 5 | 不支持事务,若当前有事务则抛异常 |
PROPAGATION_NESTED | 6 | 嵌套事务,如果当前有事务,则开启一个嵌套事务,最终会和外部事务一起提交 |
2. 事务隔离特性(数据库的)
事务隔离特性
隔离特性 | 值 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
ISOLATION_READ_UNCOMMITED | 1 | √ | √ | √ |
ISOLATION_READ_COMMITED | 2 | × | √ | √ |
ISOLATION_REPEATABLE_READ | 3 | × | × | √ |
ISOLATION_SERIALIZABLE | 4 | × | × | × |
二、编程式事务和声明式事务
1. 编程式事务
使用TransactionTemplate.execute(TransactionCallback<T> callback)
- TransactionCallback
- TransactionCallbackWithoutResult
PlatformTransactionManager
可以设置TransactionDefinition事务传播范围
2. 声明式事务
这里有一张spring官网的图(参见 这里)
开启事务注解的方式
- 注解 @EnableTransactionManagement
- xml配置 <tx:annotation-driven />
配置事务管理属性
- proxyTargetClass - false: 基于jdk接口(默认) 或 true :cglib 的动态代理
- mode - advice mode : 基于jdk proxy (默认) 或 基于 aspectj编织 的增强模式
- order - aop拦截的顺序,默认最低级别
@Transactional注解的属性
- transactionManager
- propagation
- isolation
- timeout
- readOnly
三、数据库错误码定制异常
数据库错误码配置文件 在 spring-jdbc-xxx.jar中
路径 /org/springframework/jdbc/support/sql-error-codes.xml
自定义(定制)的时候,取文件名 sql-error-codes.xml 放在 /src/resources (即classpath)下,覆盖想定制的数据库,例如
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="H2" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="badSqlGrammarCodes">
<value>42000,42001,42101,42102,42111,42112,42121,42122,42132</value>
</property>
<property name="duplicateKeyCodes">
<value>23001,23505</value>
</property>
<property name="dataIntegrityViolationCodes">
<value>22001,22003,22012,22018,22025,23000,23002,23003,23502,23503,23506,23507,23513</value>
</property>
<property name="dataAccessResourceFailureCodes">
<value>90046,90100,90117,90121,90126</value>
</property>
<property name="cannotAcquireLockCodes">
<value>50200</value>
</property>
<property name="customTranslations">
<bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">
<property name="errorCodes" value="23001,23505" />
<property name="exceptionClass" value="xx.xx.xx.XxException" />
</bean>
</property>
</bean>
</beans>
xx.xx.xx.XxException 应继承 org.springframework.dao.DataAccessException