Spring框架為事務(wù)管理提供了一致的抽象,可以帶來以下好處:
- Java Transaction API(JTA),JDBC,Hibernate,Java Persistence API(JPA)和Java數(shù)據(jù)對象(JDO)等不同的事務(wù)API之間的一致的編程模型
- 支持聲明事務(wù)管理
- 編程式事務(wù)管理的API使用簡單
- 與Spring的數(shù)據(jù)訪問抽象集成
1、Spring一致的編程模型
傳統(tǒng)上,Java EE開發(fā)人員有兩種交易管理選擇:全局或本地交易,兩者都有明顯的局限性。
- 全局事務(wù)
JTA、EJB
優(yōu)點:可以多資源使用
缺點:JTA API笨重、通過JNDI獲取資源。
- 本地事務(wù)
本地事務(wù)是資源專用,比如:JDBC連接。
優(yōu)點:簡單易用。
缺點:不能多資源使用。
1.1、理解Spring事務(wù)抽象
Spring事務(wù)抽象最重要是事務(wù)策略概念,事務(wù)策略由org.springframework.transaction.PlatformTransactionManager定義:
public interface PlatformTransactionManager {
TransactionStatus getTransaction(
TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
TransactionStatus表示一個新的事務(wù)或者當(dāng)前調(diào)用堆棧中存在匹配事務(wù),和執(zhí)行線程相關(guān)聯(lián)。TransactionStatus實例需要依賴一個
TransactionDefinition實例參數(shù),TransactionDefinition接口定義如下:
public interface TransactionDefinition {
// 事務(wù)傳播
int getPropagationBehavior();
// 事務(wù)隔離級別
int getIsolationLevel();
// 事務(wù)超時事務(wù)
int getTimeout();
boolean isReadOnly();
String getName();
}
TransactionStatus接口定義:
public interface TransactionStatus extends SavepointManager, Flushable {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
1.2、理解聲明式事務(wù)
關(guān)于Spring Framework的聲明式事務(wù)支持的最重要的概念是通過AOP代理啟用此支持,并且事務(wù)性建議由元數(shù)據(jù)驅(qū)動(目前基于XML或基于注釋的),AOP與事務(wù)元數(shù)據(jù)的組合產(chǎn)生一個AOP代理,它使用TransactionInterceptor與適當(dāng)?shù)腜latformTransactionManager實現(xiàn)結(jié)合來驅(qū)動方法調(diào)用的事務(wù)。
事務(wù)調(diào)用過程如下:

1.2.1、聲明式事務(wù)示例
-
基于XML方式
(1)創(chuàng)建對應(yīng)數(shù)據(jù)庫DO
public class User { private Integer id; private String name; private Integer age; private Integer sex; public User(Integer id, String name, Integer age, Integer sex) { this.id = id; this.name = name; this.age = age; this.sex = sex; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } }(2)、創(chuàng)建表與實體間映射
public class UserRowMapper implements RowMapper<User>{ public User mapRow(ResultSet resultSet, int i) throws SQLException { User person = new User( resultSet.getInt("id"), resultSet.getString("name"), resultSet.getInt("age"), resultSet.getInt("sex")); return person; } }(3)、創(chuàng)建UserService接口
public interface UserService { void save(User user); }(4)、創(chuàng)建UserService接口實現(xiàn)類
public class UserServiceImpl implements UserService { private final static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); @Resource private JdbcTemplate jdbcTemplate; @Override public void save(User user) { jdbcTemplate.update("INSERT INTO user(name,age,sex) VALUES (?,?,?)", new Object[]{user.getName(), user.getAge(), user.getSex()}, new int[]{Types.VARCHAR, Types.INTEGER, Types.VARCHAR}); } }(5)、創(chuàng)建Spring配置文件
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <!-- the transactional semantics... --> <tx:attributes> <!-- all methods starting with 'get' are read-only --> <tx:method name="get*" read-only="true"/> <!-- other methods use the default transaction settings (see below) --> <tx:method name="*"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* com.codersm.study.spring.tx.service.UserService.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/> </aop:config> <bean id="userService" class="com.codersm.study.spring.tx.service.impl.UserServiceImpl"/> 基于注解方式
1.3、事務(wù)傳播
1.4、其他
1.4.1、Using @Transactional with AspectJ
It is also possible to use the Spring Framework’s @Transactional support outside of a Spring container by means of an AspectJ aspect.
1.4.2、事務(wù)綁定事件
1.5 源碼分析
<<tx:advice>>標(biāo)簽 = org.springframework.transaction.interceptor.TransactionInterceptor
