2014-09-04 27 views
0

我想將我的axis2項目與spring集成。按照本指南,我設法加載了一個spring applicationContext。Hibernate4,Spring4,Axis2和@Transactional註釋未打開事務:get沒有活動事務無效

https://axis.apache.org/axis2/java/core/docs/spring.html

- 短
這裏是我的Axis2 VersionService:

public class VersionService extends MyappService{ 

    private static final Logger log = Logger.getLogger(VersionService.class); 

    @Autowired 
    NewUserMyappDAO newUserMyappDAO; 

    public Response getResponse(){ 
     Response response = new Response(); 
     UserMyapp ub = getTransaction(); 
     return response; 
    } 

    @Transactional 
    public UserMyapp getTransaction(){ 
     return newUserMyappDAO.findById(13); 
    } 
} 

問題:當軸調用GETRESPONSE()方法的DAO設法獲得注入的SessionFactory的(和hibernate會話),但是當@Transactional用在方法的頂部時,事務之前沒有打開事務。這就是爲什麼我得到得到:

Caused by: org.hibernate.HibernateException: get is not valid without active transaction 
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:348) 
at $Proxy45.get(Unknown Source) 
at com.myapp.framework.model.dao.NewMyappDAO.findById(NewMyappDAO.java:35) 
at com.myapp.ws.version.VersionService.getTransaction(VersionService.java:127) 
at com.myapp.ws.version.VersionService.getResponse(VersionService.java:119) 

我想是有某些東西在它失敗時自動啓動交易(休眠session.beginTransaction())和回滾一個getTransaction()方法是什麼。

我還試圖刪除

<prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop> 

但在這種情況下,春季加載失敗,因爲org.hibernate.HibernateException的userMyAppDAO:無會話發現當前線程

詳細
我的applicationContext.xml如下所示:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> 


    <context:annotation-config /> 

    <context:component-scan base-package="com.myapp.framework.model.dao"></context:component-scan> 

    <!-- Axis2 Web Service, but to Spring, its just another bean that has dependencies --> 
    <bean id="versionService" class="com.myapp.ws.version.VersionService"/> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
     <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
     <property name="url" value="jdbc:mysql://db.myapp.com:3307/MyappAPI" /> 
     <property name="username" value="myapp" /> 
     <property name="password" value="myappculomyapp" /> 
    </bean> 


    <bean id="sessionFactory" 
       class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 

     <property name="packagesToScan"> 
      <list> 
       <value>com.myapp.framework.model.dao</value> 
      </list> 
     </property> 

     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop> 

       <prop key="hibernate.connection.CharSet">utf8</prop> 
       <prop key="hibernate.connection.characterEncoding">utf8</prop> 
       <prop key="hibernate.connection.useUnicode">true</prop> 
       <prop key="hibernate.show_sql">false</prop> 
       <prop key="hibernate.format_sql">true</prop> 
       <prop key="hibernate.use_sql_comments">true</prop> 
       <prop key="hibernate.globally_quoted_identifiers">true</prop> 
       <prop key="hibernate.connection.autocommit">false</prop> 

       <prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop> 
       <prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory</prop> 

       <prop key="hibernate.cache.use_second_level_cache">true</prop> 
       <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> 

      </props> 
     </property> 
    </bean> 

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

    <tx:annotation-driven transaction-manager="transactionManager" /> 

</beans> 

和這裏的DAO和其超:

@Repository 
public class NewUserMyappDAO extends NewMyappDAO<UserMyapp, Integer>{ 

    @Autowired 
    public NewUserMyappDAO(SessionFactory sessionFactory){ 
     super(UserMyapp.class, sessionFactory); 
    } 
} 

@Repository 
public abstract class NewMyAppDAO<E, ID extends Serializable> 
     implements IMyAppDAO<E, ID> { 

    private final Class<E> entityClass; 
    protected Session session; 

    public NewMyAppDAO(Class<E> entityClass, SessionFactory sessionFactory) { 

     this.entityClass = entityClass; 
     this.session = sessionFactory.getCurrentSession(); 
    } 

    public Class<E> getEntityClass() { 
     return entityClass; 
    } 

    @SuppressWarnings({ "unchecked" }) 
    public E findById(ID id) { 
     Object obj = null; 
     try { 
      obj = session.get(getEntityClass(), id); 
     } catch(ObjectNotFoundException e){ 
      return null; 
     } 
     return (E) obj; 
    } 

編輯

通過vp8106留下的答案似乎以正確的方式進行下去,但我試圖backwords挪動一步試圖以編程方式管理交易。我所做的是在getResponse()方法中明確使用beginTransaction(),commitTransaction(),rollbackTransaction()和close()。即使SessionFactory對象是單身,它與

<prop key="hibernate.current_session_context_class">thread</prop> 

初始化沒有開始事務和吾道仍返回相同的異常。

+1

這'org.hibernate.HibernateException:無會話發現當前thread'例外告訴你,你有沒有配置交易正確並且不是通過簡單地使用另一個當前會話上下文來解決的。你的'VersionService'不是一個Spring的管理bean,因爲這樣的事務將不起作用。確保它是完全sprnig託管bean(包括代理創建)。 – 2014-09-04 15:04:28

+0

感謝您的回覆。我不明白如何檢查它。軸心使它很難理解。我的意思是,userMyAppDAO被正確注入,所以我認爲我正在使用spring管理的bean。 – ecostanzi 2014-09-04 15:23:16

+0

我發現這個鏈接http://stackoverflow.com/questions/8846586/no-session-found-for-current-thread-spring-3-1-x-and-hibernate-4。它建議將註解驅動的設置移動到servlet上下文,而不是將它們留在應用程序上。看來我應該創建一個axis2-servlet.xml並以某種方式將它傳遞給axis2 servlet。 – ecostanzi 2014-09-05 09:05:16

回答

1

安訊士有可能稱爲getResponse春豆的方法沒有標記@Transactional。事實是,春天爲豆類創建了一個動態代理,其方法註釋爲@Transactional。該代理將調用包裝到事務處理之前,並在目標方法執行後進行提交。但在你的方法getResponse調用方法getTransaction這個豆,而不是代理。因此,事務感知代碼不會執行,並且沒有事務開始。

最簡單可能的解決方案是用@Transactional而不是getTransaction來標記getResponse方法。注意:只有在彈簧生成的代理上調用了getResponse,它纔會起作用,這從您提供的堆棧跟蹤中不明確。

編輯
在Spring環境中,你應該使用

<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop> 

它結合Hibernate的Session的生命週期到春節的HibernateTransactionManager。

爲了啓動,提交或回滾事務,應該使用HibernateTransactionManager的.getTransaction(...)commit(...)rollback(...)而不是hibernate Session的方法。要以編程方式管理事務,最好使用TransactionTemplate,它可以幫助您避免編寫樣板代碼以開始,落實或回滾事務。

+0

感謝您的回覆。我只是編輯了答案,以便了解它是春季還是冬眠。 – ecostanzi 2014-09-12 16:05:35

+0

我編輯了答案。我希望這會有所幫助。 – vp8106 2014-09-13 19:17:29

+0

它仍在拋出org.hibernate.HibernateException:在將應用程序加載到tomcat時,在org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)中找不到當前線程的會話。看看代碼,我發現在SpringSessionContext類中的行TransactionSynchronizationManager.getResource(this.sessionFactory);返回一個空值。它可能需要做的事情,豆作爲根上下文加載,而不是servlet上下文。 – ecostanzi 2014-09-15 08:34:26

0

感謝vp816和M. Deinum,我設法瞭解發生了什麼事。

  1. 最大的失誤在這裏是,我是用我每次打電話NewMyAppDAO的findById方法時相同的私有會話字段對象。使用受保護的getSession()方法可以正確使用會話。

    @Repository 公共抽象類NewMyAppDAO 實現IMyAppDAO {

    private final Class<E> entityClass; 
    protected SessionFactory sessionFactory; 
    
    public NewMyAppDAO(Class<E> entityClass, SessionFactory sessionFactory) { 
    
        this.entityClass = entityClass; 
        this.sessionFactory = sessionFactory; 
    } 
    
    protected Session getSession(){ 
        return this.sessionFactory.getCurrentSession(); 
    } 
    

    }

  2. 使用編程式事務管理我們必須設置該屬性

    <prop key="hibernate.current_session_context_class">thread</prop> 
    

    彈簧設定值:

    <tx:annotation-driven> 
    

    在這種情況下是無用的。

  3. 如果我們要使用春註解驅動的事務我們已經到:
    一)從SessionFactory的bean配置
    b)將彈簧設置 <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> C)刪除hibernate.current_session_context_class財產春豆使用@Transactional註解axis2服務除外。事實上,他們的加載似乎發生在春天無法創建代理的方式。在我的情況下,解決方案是創建一個Spring註釋的服務並將其方法設置爲事務性。

    @Service 公共類VersionHandler {

    @Autowired 
    NewUserMyappDAO newUserMyappDAO; 
    
    @Transactional 
    public UserMyapp getUserMyapp(int transactionId){ 
        return newUserMyappDAO.findById(transactionId); 
    } 
    

    }

相關問題