2011-06-20 31 views
5

Tôi đang viết một bean đơn giản mà tôi muốn cấu hình với một tên bảng, một tệp XML với một số dữ liệu, để nếu lúc khởi động ứng dụng, bảng sẽ trống, nó sẽ được khởi tạo với dữ liệu đó. Tôi quyết định sử dụng các truy vấn SQL đơn giản, nhưng tôi không thể có được một phiên từ sessionfactory, vì nó nói:Tại sao tôi không thể tạo hạt này @Transactional trong mùa xuân?

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

Nhưng đây là cấu hình (rất giống với một dịch vụ):

<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> 

và tôi đã chú thích phương thức init() bằng @Transactional. Nhưng nó không bắt đầu một giao dịch và tôi nhận được rằng lỗi:

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

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

tại sao không làm việc đó?

Trả lời

15

Phương thức chú thích init-method hoặc @PostConstruct không được proxy, do đó bạn sẽ không thể sử dụng @Transactional trên đó. Bạn nên sử dụng @Transactional trên dịch vụ của mình, tại sao lại không phù hợp với bạn? Phần trích dẫn từ 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.

Như đã trình bày, bạn có thể thử mode="aspectj" mà bạn nên xem lại thiết kế của bạn theo ý kiến ​​của tôi.

+1

+1 cho liên kết có liên quan và “xem xét thiết kế của bạn”. –

+0

Tôi đã xem xét thiết kế của mình ... rất đơn giản, tôi đặt một tham chiếu đến dịch vụ của tôi và đó là tất cả. Tại sao tôi muốn tránh điều này? Bởi vì tôi muốn tạo một thư viện độc lập thực sự, ngay cả từ dịch vụ của tôi và sử dụng lại nó, thậm chí có thể đặt nó trực tuyến dưới GPL ... Dù sao, @Donal, tất nhiên là dễ dàng hơn để làm điều này ngay từ đầu, nhưng nếu bạn không bao giờ thúc đẩy một giải pháp mới, khó khăn như nó có thể được, bạn không bao giờ nhận được bất cứ điều gì mới và hữu ích. – gotch4

+0

Mất 5 giờ vào ngày hôm nay. Nếu tôi có thể upvote câu hỏi và trả lời 1000 lần tôi sẽ! – HDave

2

Tôi không nghĩ bạn có thể thực hiện giao dịch phương thức init. Nhưng bạn có thể gọi phương thức giao dịch khác của một dịch vụ khác từ nó.

+0

Tôi có thể gọi trực tiếp cho Dao và thực hiện giao dịch dao (điều này nghe có vẻ ngu ngốc, nhưng cho đến bây giờ tôi chỉ thực hiện các phương thức dịch vụ giao dịch, vì vậy hãy kiên nhẫn)? – gotch4

+2

bạn có thể, nhưng thông thường bạn không nên. – Bozho

Các vấn đề liên quan