Spring提供兩種方式實現編程式的交易管理,一是直接使用PlatformTransactionManager實現,二是使用org.springframework.transaction.support.TransactionTemplate。
先來看看如何使用PlatformTransactionManager,在這邊使用它的實現類別DataSourceTransactionManager,可以改寫一下 使
用 JdbcTemplate,讓它具有交易管理功能,修改一下UserDAO類別的insert()方法來作示範:
package onlyfun.caterpillar;
import java.util.Iterator; import java.util.List; import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc. datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction. support.DefaultTransactionDefinition;
public class UserDAO implements IUserDAO { private DataSourceTransactionManager transactionManager; private DefaultTransactionDefinition def; private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); transactionManager = new DataSourceTransactionManager(dataSource); // 建立交易的定義 def = new DefaultTransactionDefinition(); def.setPropagationBehavior( TransactionDefinition.PROPAGATION_REQUIRED); } public void insert(User user) { String name = user.getName(); int age = user.getAge().intValue(); TransactionStatus status = transactionManager.getTransaction(def); try { jdbcTemplate.update("INSERT INTO user (name,age) " + "VALUES('" + name + "'," + age + ")"); // 下面的SQL有錯誤,用以測試交易 jdbcTemplate.update("INSER INTO user (name,age) " + "VALUES('" + name + "'," + age + ")"); } catch(DataAccessException e) { transactionManager.rollback(status); throw e; } transactionManager.commit(status); }
public User find(Integer id) { List rows = jdbcTemplate.queryForList( "SELECT * FROM user WHERE id=" + id.intValue()); Iterator it = rows.iterator(); if(it.hasNext()) { Map userMap = (Map) it.next(); Integer i = new Integer( userMap.get("id").toString()); String name = userMap.get("name").toString(); Integer age = new Integer( userMap.get("age").toString());
User user = new User(); user.setId(i); user.setName(name); user.setAge(age); return user; }
return null; } }
在insert()方法中使用了DataSourceTransactionManager來進行交易管理,如果發生了例外,則catch區塊中會進行交
易的回滾(Rollback),在insert()方法中固定撰寫錯有錯誤的SQL(注意INSERT方法少寫了一個T),因此實際上資料並不會被儲存至
資料庫中。
要使用MySQL資料庫的交易處理,必須建立交易類型的表格,例如InnoDB類型的表格,我這邊用來建立表格的SQL如下所示:
CREATE TABLE user (
id INT(11) NOT NULL auto_increment PRIMARY KEY,
name VARCHAR(100) NOT NULL default '',
age INT
) TYPE = InnoDB;
另一個實現編程式交易管理的方法是使用TransactionTemplate,它需要一個TransactionManager實例,一個例子如下所示:
...
TransactionTemplate transactionTemplate =
new TransactionTemplate(transactionManager);
...
transactionTemplate.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
jdbcTemplate.update("INSERT INTO user (name,age) "
+ "VALUES('" + name + "'," + age + ")");
...
}
catch(DataAccessException e) {
status.setRollbackOnly();
}
return result; // commit
}
});
如果發生了例外,則會進行回滾,否則提交交易,如果沒有返回值,則也可以使用TransactionCallbackWithoutResult:
...
transactionTemplate.execute(
new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(
TransactionStatus status) {
. ...
}
});
|