2011-06-20 59 views
5

我正在寫一個簡單的bean,我想用一個表名稱來配置一個帶有一些數據的XML文件,這樣,如果在應用程序啓動時表格是空的,它將使用該數據進行初始化。我決定使用簡單的SQL查詢,但我不能獲得通過SessionFactory會話,因爲它說:爲什麼我不能在Spring中創建這個bean @Transactional?

Error creating bean with name 'vecchiOrdiniFiller' defined in ServletContext resource [/WEB-INF/spring/servlet-context.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

但這是配置(非常類似於服務):

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="mySessionFactory" /> 
</bean> 

<tx:annotation-driven /> 

<bean id="ordiniVecchioSistemaLoader" class="it.jsoftware.jacciseweb.assistenza.common.ExcelXmlDataLoader"> 
    <property name="xmlFileName" value="WEB-INF/data/daticlientijaccisemarco.xml"></property> 
</bean> 

<bean id="vecchiOrdiniFiller" class="it.jsoftware.jacciseweb.assistenza.common.BaseTableFiller" init-method="init"> 
    <property name = "sessionFactory" ref = "mySessionFactory"></property> 
    <property name="loader" ref="ordiniVecchioSistemaLoader"></property>  
    <property name="tableCreationString" value="CREATE TABLE `vecchiordini` ( `ID` INT(11) NOT NULL AUTO_INCREMENT, `codicejazz` VARCHAR(255) DEFAULT NULL, `progressivolicenza` INT(11), `codicearticolo` VARCHAR(255) DEFAULT NULL, `rivenditore` VARCHAR(255) DEFAULT NULL, `cliente` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`ID`)) ENGINE=INNODB DEFAULT CHARSET=utf8"></property> 
    <property name="table" value="vecchiordini"></property> 
    <property name="tableColumns"> 
     <list> 
      <value>codicejazz</value> 
      <value>progressivolicenza</value> 
      <value>codicearticolo</value> 
      <value>rivenditore</value> 
      <value>nomecliente</value> 
     </list> 
    </property> 
    <property name="loaderColumns"> 
     <list> 
      <value>clicod</value> 
      <value>licsmatricola</value> 
      <value>artcod</value> 
      <value>rivenditore</value> 
      <value>cliente</value> 
     </list> 
    </property> 
</bean> 

我用@Transactional註解了init()方法。不過,這並不啓動一個事務,我得到這個錯誤:

@Transactional 
public void init() throws Exception { 
    logger.info("BaseTableFilter per tabella: " + table + ", usando: " 
    + loader.getSourceName()); 

    Session session = dao.getSession(); 
    Transaction tx = session.beginTransaction(); 
    ... 

爲什麼不運作的?

回答

15

init-method@PostConstruct註釋的方法沒有被代理,所以你將無法使用@Transactional。你應該對你的服務使用@Transactional,爲什麼不適合你? 從SpringSource Jira引用:

This is as defined, actually: init methods (such as @PostConstruct methods) are always called on the target instance itself. The proxy will only be generated once the target instance has been fully initialized... In other words, the @Transactional proxy isn't even created at the point of the @PostConstruct call yet.

Switching to mode="aspectj" would help since it weaves the target class directly, in which case the init method will have been modified for transactional awareness at the time of the container init call already.

I guess at the very minimum, we should document the limitations of @Transactional on proxies more clearly - and point out where mode="aspectj" might be a solution.

如前所述,你可以嘗試mode="aspectj"而是應該檢查你的設計在我看來。

+1

+1相關鏈接和「審查您的設計」。 –

+0

我確實審查了我的設計......很簡單,我提到了我的服務,這就是全部。爲什麼我想避免這種情況?因爲我想要建立一個真正的獨立圖書館,甚至可以從我的服務中重新使用它,甚至可以把它放在GPL的網上...無論如何,@Donal,從一開始就很容易做到這一點,但如果你從不推動新的解決方案,儘可能棘手,你永遠不會得到任何新的和有用的東西。 – gotch4

+0

今天失去了5個小時。如果我可以upvote問題,並回答1000次我會! – HDave

2

我不認爲你可以使init方法事務。但是您可以從中調用另一個服務的另一個事務方法。

+0

我可以直接調用Dao並使dao方法事務化(這可能聽起來很愚蠢,但到現在爲止我只是將服務方法變成事務性的,請耐心等待)? – gotch4

+2

你可以,但通常你不應該。 – Bozho

相關問題