在本系列的上一篇文章中,我們講到了使用TransactionManger和ConnectionHolder完成線程安全的事務管理,在本篇中,我們將在此基礎上引入Template模式進行事務管理。
Template模式大家應該都很熟悉,比如Spring就提供了許多Template,像JdbcTemplate和JmsTemplate等。Template模式的基本思想是:在超類裏將完成核心功能的方法聲明爲抽象方法,留給子類去實現,而在超類中完成一些通用操作,比如JMS的Session的建立和數據庫事務的準備工作等。
在本篇文章中,我們使用一個Template類來幫助管理事務,定義TransactionTemplate類如下:
package davenkin.step4_transaction_template;
import davenkin.step3_connection_holder.TransactionManager;
import javax.sql.DataSource;
public abstract class TransactionTemplate
{
private TransactionManager transactionManager;
protected TransactionTemplate(DataSource dataSource)
{
transactionManager = new TransactionManager(dataSource);
}
public void doJobInTransaction()
{
try
{
transactionManager.start();
doJob();
transactionManager.commit();
} catch (Exception e)
{
transactionManager.rollback();
} finally
{
transactionManager.close();
}
}
protected abstract void doJob() throws Exception;
}
在TransactionTemplate類中定義一個doJobInTransaction方法,在該方法中首先使用TransactionManager開始事務,然後調用doJob方法完成業務功能,doJob方法爲抽象方法,完成業務功能的子類應該實現該方法,最後,根據doJob方法執行是否成功決定commit事務或是rollback事務。
然後定義使用TransactionTemplate的TransactionTemplateBankService:
package davenkin.step4_transaction_template;
import davenkin.BankService;
import davenkin.step3_connection_holder.ConnectionHolderBankDao;
import davenkin.step3_connection_holder.ConnectionHolderInsuranceDao;
import javax.sql.DataSource;
public class TransactionTemplateBankService implements BankService
{
private DataSource dataSource;
private ConnectionHolderBankDao connectionHolderBankDao;
private ConnectionHolderInsuranceDao connectionHolderInsuranceDao;
public TransactionTemplateBankService(DataSource dataSource)
{
this.dataSource = dataSource;
connectionHolderBankDao = new ConnectionHolderBankDao(dataSource);
connectionHolderInsuranceDao = new ConnectionHolderInsuranceDao(dataSource);
}
public void transfer(final int fromId, final int toId, final int amount)
{
new TransactionTemplate(dataSource)
{
@Override
protected void doJob() throws Exception
{
connectionHolderBankDao.withdraw(fromId, amount);
connectionHolderInsuranceDao.deposit(toId, amount);
}
}.doJobInTransaction();
}
}
在TransactionTemplateBankService的transfer方法中,我們創建了一個匿名的TtransactionTemplate類,並且實現了doJob方法,在doJob方法中調用兩個DAO完成業務操作,然後調用調用TransactionTemplateBankService的doJobInTransaction方法。
由於TransactionTemplate只是對上一篇文章中事務處理的一層封裝,故TransactionManager和兩個DAO類都保持和上一篇中的一樣,此時他們都使用SingleThreadConnectionHolder獲得Connection,故事務處理成功。
在下一篇文章中,我們會講到使用Java的動態代理來完成事務處理,這也是Spring管理事務的典型方法。