[英]How to manage 2 DAO methods in a single transaction in Java Spring and Hibernate?
[英]Two dao methods in a single Spring @Transaction
我正在使用Spring的@Transactional和Hibernate。 我試圖將兩個dao方法放入單個事務中,並希望在特定的Exception上回滾。 代碼如下:
服務類別方法:
@Transactional(propagation=Propagation.REQUIRES_NEW,value="txManager",rollbackFor=TransactionUnSuccessException.class)
public Account makeTransaction(Transaction transaction, String userName)
throws TransactionUnSuccessException {
Account account = null;
account = transferDao.makeTransaction(transaction, userName);
return account;
}
道方法:
@Repository
public class TransferDao extends HibernateDaoSupport {
@Autowired
private SessionFactory sessionFactory;
public Account makeTransaction(Transaction transaction, String userName)
throws TransactionUnSuccessException {
HibernateTemplate hibernateTemplate = getHibernateTemplate();
Account account = null;
Session session = hibernateTemplate.getSessionFactory().openSession();
//session.beginTransaction();
updateSelfAccount(transaction, userName, session);
account = updateAnotherAcccount(transaction, session);
//session.getTransaction().commit();
return account;
}
private void updateSelfAccount(Transaction transaction, String userName,
Session session) {
User currentUser = null;
System.out.println("TransferDao.updateSelfAccount()" + transaction);
Query query = session.createQuery("from User where userName=:userName");
query.setParameter("userName", userName);
currentUser = (User) query.list().get(0);
currentUser.getAccount().getTransactions().add(transaction);
currentUser.getAccount().setAvailableBalance(
currentUser.getAccount().getAvailableBalance()
- transaction.getAmount());
transaction.setTransAccount(currentUser.getAccount());
session.save(transaction);
session.update(currentUser.getAccount());
session.update(currentUser);
private Account updateAnotherAcccount(Transaction transaction,
Session session) throws TransactionUnSuccessException {
Account account = null;
try {
Query query = session
.createQuery("from Account where accNo=:accNo");
query.setParameter("accNo", transaction.getToAcc());
account = (Account) query.list().get(0);
if (account.getAvailableBalance() < 5000) {
account.setAvailableBalance(account.getAvailableBalance()
+ transaction.getAmount());
account.getTransactions().add(transaction);
transaction.setTransAccount(account);
session.save(transaction);
session.update(account);
} else {
throw new TransactionUnSuccessException();
}
} catch (TransactionUnSuccessException te) {
te.printStackTrace();
}
return account;
}
}
}
XML配置:
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
如果兩個方法(updateSelfAccount,updateAnotherAcccount)中的任何一個失敗,則應該回滾整個事務。 但是,即使我不確定這是否在單個事務中全部發生,它也無法回滾給定的異常。 請糾正我。
使用@Transactional批注的目標是您的代碼不應處理事務本身。 在您的代碼示例中,您使用@Transactional,因此您不必做類似的事情
session.beginTransaction();
您是否使用其他方法正確設置了spring
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="datasource" ref="dataSource"
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
通常,sessionFactory在dao中為@Autowired,以便輕松訪問您執行的會話
sessionFactory.getCurrentSession()
最后一點,您不需要費勁嘗試,然后拋出TransactionUnSuccessException,默認情況下,事務將在發生任何異常時回滾。
對於初學者,請勿使用HibernateTemplate
和/或HibernateDaoSupport
,應將其視為已棄用。 直接使用SessionFactory
。 接下來,永遠不要在Spring托管的事務中使用openSession
,因為它將在新會話中打開新會話,而不綁定到事務和Spring外部。 在SessionFactory
上使用getCurrentSession
代替。
最后, 絕不捕獲並吞下異常,spring的TransactionInterceptor需要異常來決定要做什么(回滾或提交)
重構您的DAO以包括所有這一切。
@Repository
public class TransferDao {
@Autowired
private SessionFactory sessionFactory;
private Session getSession() {
sessionFactory.getCurrentSession();
}
public Account makeTransaction(Transaction transaction, String userName) throws TransactionUnSuccessException {
Account account = null;
Session session = getSession();
updateSelfAccount(transaction, userName, session);
account = updateAnotherAcccount(transaction, session);
return account;
}
從更新的數量來看,另一個觀察結果是您有映射問題。 當您的映射正確時,您只需要費心處理User
對象的更新/保存,然后其他所有內容都將自動保留。
還有另一點觀察,您不應繞過會話,只需調用getSession()
方法(已將其添加到dao中)即可。 在整個交易過程中,您應該獲得相同的Session
。
最終觀察到,您的dao似乎包含業務邏輯,而應該在服務方法中(例如,檢查帳戶余額)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.