2012-06-26 53 views
1

我想在JSF2-Spring-Hibernate Web App中實現Session-Per-Conversation模式,所以我需要我的AnnotationSessionFactoryBean來構建一個帶有自定義CurrentSessionContext類的Hibernate SessionFactory。不能在Spring Session Factory中設置自定義的CurrentSessionContext類

我已經收到此錯誤日誌:

org.springframework.dao.DataAccessResourceFailureException: Could not obtain Hibernate-managed Session for Spring-managed transaction; nested exception is org.hibernate.HibernateException: No CurrentSessionContext configured! 

這裏是我使用的整個數據上下文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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-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-3.0.xsd"> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
     <property name="driverClassName" value="${datasource.driverClassName}" /> 
     <property name="url" value="${datasource.url}" /> 
     <property name="username" value="${datasource.username}" /> 
     <property name="password" value="${datasource.password}" /> 
     <property name="initialSize" value="${datasource.poolInitialSize}" /> 
    </bean> 

    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="configLocation" value="classpath:hibernate.cfg.xml" /> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">${org.hibernate.dialect.dialectmysqlInno}</prop> 
       <prop key="hibernate.hbm2ddl.auto">${org.hibernate.ddl.mode}</prop> 
       <prop key="hibernate.search.default.directory_provider">${org.hibernate.search.directoryprovidr}</prop> 
       <prop key="hibernate.current_session_context_class"> 
        mx.gob.jgtjo.apps.schedule.web.conversation.ConversationalCurrentSessionContext 
       </prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="transactionManager" 
     class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="hibernateManagedSession" value="true" /> 
    </bean> 

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

    <context:component-scan base-package="mx.gob.jgtjo.apps.schedule.dao.hibernate" /> 

</beans> 

而且,這裏是我的hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
             "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 
    <session-factory name="jgtjoSessionFactory"> 
     <!--Entity --> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.AudienciaOral" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.CausaPenal" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.DefensorPenal" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.Delito" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.EventoAudiencia" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.Juez" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.MinisterioPublico" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.ParteMaterial" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.Sala" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.TipoAudiencia" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.User" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.Rol" /> 
     <mapping class="mx.gob.jgtjo.apps.schedule.model.DelitoConfigurado" /> 
    </session-factory> 
</hibernate-configuration> 

正如你所看到的,沒有什麼棘手與Hibernate XML。

爲什麼我不斷收到此異常?

java.lang.NoSuchMethodException: mx.gob.jgtjo.apps.schedule.web.conversation.ConversationalCurrentSessionContext.<init>(org.hibernate.engine.SessionFactoryImplementor) 

似乎hibernate在我的類中尋找一個構造函數,它有一個SessionFactory作爲參數。

回答

1

好的,正如上面的anwer向我展示了我在我的問題中顯示的代碼和日誌記錄,編輯CurrentSessionContext接口的實現必須具有一個以sessionFactory作爲參數的公共構造函數。

Hibernate文檔從來沒有這樣說過。

,這裏是我的課:

package mx.gob.jgtjo.apps.schedule.web.conversation; 

import javax.servlet.http.HttpServletRequest; 

import mx.gob.jgtjo.apps.schedule.web.utils.JsfUtils; 

import org.hibernate.HibernateException; 
import org.hibernate.classic.Session; 
import org.hibernate.context.CurrentSessionContext; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class ConversationalCurrentSessionContext implements CurrentSessionContext { 

    private static final long serialVersionUID = 803157986557235023L; 

    protected static final Logger log = LoggerFactory 
      .getLogger(ConversationalCurrentSessionContext.class); 

    public ConversationalCurrentSessionContext() { 

    } 

    @Override 
    public Session currentSession() throws HibernateException { 

     HttpServletRequest request = null; 

     try { 
      request = JsfUtils.getCurrentHttpRequest(); 
     } catch (Exception e) { 
      log.debug("No current http request in faces context, returning default conversation."); 
     } 

     if (request == null) { 
      return (Session) ConversationManager.getDefaultConversationSession(); 
     } else { 
      return (Session) ConversationManager.getSessionForRequest(request); 
     } 
    } 
} 

正如你所看到的,我沒有這個構造。

1

這是從休眠,它試圖建立使用您在使用hibernate.current_session_context_class屬性傳遞任何值當前會話的上下文代碼:

private CurrentSessionContext buildCurrentSessionContext() { 
     String impl = properties.getProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS); 
     // for backward-compatability 
     if (impl == null && transactionManager != null) { 
      impl = "jta"; 
     } 

     if (impl == null) { 
      return null; 
     } 
     else if ("jta".equals(impl)) { 
      if (settings.getTransactionFactory().areCallbacksLocalToHibernateTransactions()) { 
       log.warn("JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()"); 
      } 
      return new JTASessionContext(this); 
     } 
     else if ("thread".equals(impl)) { 
      return new ThreadLocalSessionContext(this); 
     } 
     else if ("managed".equals(impl)) { 
      return new ManagedSessionContext(this); 
     } 
     else { 
      try { 
       Class implClass = ReflectHelper.classForName(impl); 
       return (CurrentSessionContext) implClass 
         .getConstructor(new Class[] { SessionFactoryImplementor.class }) 
         .newInstance(new Object[] { this }); 
      } 
      catch(Throwable t) { 
       log.error("Unable to construct current session context [" + impl + "]", t); 
       return null; 
      } 
     } 
    } 

正如你可以看到可接受的值是jtathreadmanaged

由於您使用的是Spring的事務管理功能,因此您不應該設置此屬性。春天會爲你照顧這個。

您只需要使用@Transactional註釋您的交易方法,並且會話將被打開並綁定到當前線程。

+0

正如您在表3.7中看到的那樣。其他屬性接受的值是「例如jta | thread | managed | custom.Class」,並且我傳遞了類完全限定的名稱,最後您可以看到hibernate如何對我的類進行反射調用。並通過構造函數檢查會話工廠。 – ElderMael

+0

我在8小時內無法回答自己的問題。大聲笑。謝謝傑夫。 – ElderMael

+0

爲什麼hibernate文檔沒有顯示實現CurrentSessionContext的類必須具有該構造函數? – ElderMael

相關問題