2011-10-12 98 views
0

我有一個java/spring webapp使用HibernateTemplate,我想知道是否有可能使用SQL事務與休眠模板。休眠模板事務

例如,假設我有以下DAO代碼:

getHibernateTemplate().save(newObject); 
getHibernateTemplate().saveOrUpdate(someObject); 
getHibernateTemplate().delete(oldObject); 

假設我想要麼所有三個語句成功或全部三個失敗。有什麼辦法可以用hibernate模板來完成這個任務嗎?我可以使用try/catch塊嗎?如果是這樣,我會放入catch塊來回滾hibernate模板語句?

回答

0

使用Spring來管理你的交易(我把它看作你的一個標籤)。

其基本思想是將一羣持久性操作分組,一個方法(在一個服務類中)要參與一個事務,而另一個方法(configure Spring)使這個服務方法成爲事務性的。

一個比較簡單的方法就是配置spring來使所有的服務方法都成爲事務性的,但是你並沒有受到這種限制 - 你可以根據需要簡單或複雜。

+0

您能否至少鏈接到一個示例或一些相關文檔?我明白一般的想法是使用一個事務,但在HibernateTemplate API中我沒有看到任何允許這樣做的事情。 – David

+0

第二段中的'configure spring'文本中有一個鏈接。您可能需要在該文檔中聲明性的事務管理。 – hvgotcodes

+0

您可以使用org.springframework.orm.hibernate.HibernateTransactionManager實現。您必須僅設置sessionFactory屬性。在appcontext中使用此行來管理具有註釋的事務: lepike

2

正如@hvgotcodes所指出的,事務是在服務層而不是在持久層中進行管理的。這是由於事務的含義是事務性的=>大多數時間是由業務定義的,因此是服務/域層。

下面是如何通過Spring AOP XML配置交易服務的例子:

<aop:config> 
    <aop:pointcut id="moneyMakingBusinessServiceMethods" 
        expression="execution(* org.gitpod.startup.service.MoneyMakingBusinessService.*(..))"/> 

    <aop:advisor advice-ref="moneyMakingAdvice" 
       pointcut-ref="moneyMakingBusinessServiceMethods"/> 
</aop:config> 

<tx:advice id="moneyMakingAdvice" transaction-manager="txManager"> 
    <tx:attributes> 
     <tx:method name="makeMoney" propagation="REQUIRED"/> 
     <tx:method name="withdrawMoney" propagation="REQUIRED" read-only="true"/>    
     <tx:method name="*" propagation="SUPPORTS" read-only="true"/> 
    </tx:attributes> 
</tx:advice> 

這種做法是很好的,因爲你並不需要@Transactional污染你的服務,@SomethingElse註釋,和你TX管理/配置被定義在一個地方[這是我個人的信念]。

這項服務將花費道/存儲庫或兩個,並委託所有持久運作它:

public class CleverMoneyMakingBusinessService implements MoneyMakingBusinessService { 

    private MoneyRepository moneyRepository; 

    public void makeMoney(MoneyRoll money) { 
     moneyRepository.make(money); 
    } 

    public MoneyRoll withdrawMoney(Long moneyRollId) { 
     return moneyRepository.find(moneyRollId); 
    } 

    public void setMoneyRepository(MoneyRepository moneyRepository) { 
     this.moneyRepository = moneyRepository; 
    } 
} 

而存儲庫/ DAO可能看起來像這樣(請注意,它不使用HibernateTemplate,因爲@Repository做所有的異常翻譯和Hibernate SessionFactory可以和應該可以直接使用):

@Repository 
public class HibernateMoneyRepository implements MoneyRepository { 

    private SessionFactory sessionFactory; 

    public MoneyRoll find(Long rollId) { 

     MoneyRoll moneyRoll = null; 

     Query query = getSession().getNamedQuery("find.moneyroll.by.id"); 
     query.setParameter("id", rollId); 

     List<MoneyRoll> moneyList = query.list(); 

     if (moneyList.size() != 0) { 
      moneyRoll = (MoneyRoll)query.list().get(0); 
     } 

     return moneyRoll; 
    } 

    public void make(MoneyRoll moneyRoll) { 
     getSession().save(moneyRoll); 
    } 

    public void takeOut(MoneyRoll moneyRoll) { 
     getSession().delete(moneyRoll); 
    } 

    public void update(MoneyRoll money) { 

     Query query = getSession().getNamedQuery("update.moneyroll"); 
     query.setParameter("id", money.getId()); 
     query.setParameter("amount", money.getAmount()); 
     query.setParameter("currency", money.getCurrency()); 

     query.executeUpdate(); 
    } 

    private Session getSession() { 
     return sessionFactory.getCurrentSession(); 
    } 

    public void setSessionFactory(SessionFactory sessionFactory) { 
     this.sessionFactory = sessionFactory; 
    } 
} 

看看的money making project我把它們作爲一個例子,看看它們是如何結合在一起並執行的。