2016-08-29 33 views
2

私はspring-mvc、spring-security、spring-core、およびhibernateでWebアプリケーションを作成しています。事前バインドされたHibernateセッションを取得できませんでした - 現在のスレッドのトランザクション同期セッションを取得できませんでした

しかし、私はいつもhibernateセッションファクトリからこの非エラーを受け取ります。

実際にはHibernateExceptionがスローされていますが、ログにはデバッグレベルで表示され、アプリケーションは実際に問題なく実行されます。

しかし例外が発生した理由を理解することは非常に興味があります。

ログには次の行が表示されます。

2016-08-29 13:34:55,310 DEBUG [sg.com.diamond.express.base.dao.impl.HibernateDAOImpl].[doExecute]([328]) [http-nio-8888-exec-4] - Could not retrieve pre-bound Hibernate session 
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread 
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134) 
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014) 
    at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:325) 
    at org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:308) 
    at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:418) 
    at org.springframework.orm.hibernate4.HibernateTemplate.get(HibernateTemplate.java:411) 
    at sg.com.diamond.express.base.dao.impl.BaseHibernateDaoImpl.findById(BaseHibernateDaoImpl.java:160) 
    at sg.com.diamond.express.webadmin.service.impl.ClientProfileServiceImpl.searchByName(ClientProfileServiceImpl.java:48) 
    at sg.com.diamond.express.webadmin.controller.impl.ClientController.home(ClientController.java:48) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:472) 
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:409) 
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:146) 
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 

これは私のコードです。

DAOレベル

これは私がDAO、基本的なC-R-U-Dを実装する必要がないため、ボイラープレートコードの数を最小限にするために作成された抽象化レベルです。

BaseDAOインタフェース

public interface BaseDAO <ID extends Serializable, M extends BaseModel> { 
    Session getCurrentSession(); 

    M findById(ID id) throws DAOException; 
    List<M> findByCriteria(M criteria) throws DAOException; 
    List<M> listAll() throws DAOException; 
    ID saveObject(M object) throws DAOException; 
    void saveOrUpdate(M object) throws DAOException; 
    Query createQuery(String hql) throws DAOException; 
    Query createSQLQuery(String sql) throws DAOException; 
    Criteria createCriteria(Class clazz) throws DAOException; 
    List<M> runQuery(Query query) throws DAOException; 
    List<M> runQuery(String sql) throws DAOException; 
} 

BaseDAO実装

public class BaseHibernateDaoImpl<ID extends Serializable, M extends BaseModel> extends HibernateTemplate implements BaseDAO<ID, M> { 

    protected Class<M> modelClass; 

    @Override 
    public Session getCurrentSession() { 
     return this.getSessionFactory().getCurrentSession(); 
    } 

    public ID saveObject(M object) throws DAOException { 
     try { 
      object.setCreator("Batch"); 
      object.setCreatedAt(new Timestamp(new Date().getTime())); 
      object.setUpdater("Batch"); 
      object.setUpdatedAt(new Timestamp(new Date().getTime())); 
      return (ID) super.save(object); 
     } catch (Exception e) { 
      logger.error(ExceptionUtil.getStackTraces(e), e); 
      throw new DAOException(e); 
     } 
    } 

    /** all other implementation methods **/ 

春のXML構成

<!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     | Data Source Configuration 
     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> 
    <bean id="targetDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 
     <property name="url" value="jdbc:oracle:thin:@192.168.170.36:1521:EXPT2" /> 
     <property name="username" value="EXP_USER" /> 
     <property name="password" value="passw0rd" /> 
    </bean> 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> 
     <property name="targetDataSource" ref="targetDataSource"/> 
    </bean> 

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     | Hibernate abstract session factory parent 
     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> 
    <bean id="baseSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" abstract="true"> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.format_sql">true</prop> 
       <prop key="hibernate.jdbc.batch_size">10</prop> 
      </props> 
     </property> 
    </bean> 

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     | Hibernate entity configurations 
     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> 
    <bean id="expressSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" parent="baseSessionFactory"> 
     <property name="hibernateProperties"> 
      <props merge="true"> 
       <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> 
      </props> 
     </property> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="mappingLocations" value="classpath*:hbm/express/*.hbm.xml"/> 
    </bean> 

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     | Transaction Management 
     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> 
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="expressSessionFactory"/> 
    </bean> 

    <aop:config> 
     <aop:pointcut id="servicePointcut" expression="execution(* sg.com.diamond.express.webadmin.service.*.*.*(..))"/> 
     <aop:advisor id="serviceTx" advice-ref="txAdvice" pointcut-ref="servicePointcut"/> 
    </aop:config> 

    <tx:advice id="txAdvice" transaction-manager="txManager"> 
     <tx:attributes> 
      <tx:method name="get*"  propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /> 
      <tx:method name="search*" propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /> 
      <tx:method name="list*"  propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /> 
      <tx:method name="is*"  propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="true" /> 
      <tx:method name="*"   propagation="REQUIRES_NEW" isolation="READ_COMMITTED" read-only="false"/> 
     </tx:attributes> 
    </tx:advice> 

    <!--|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     | Base Dao Definitions 
     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> 
    <bean id="baseExpressDAO" class="sg.com.diamond.express.base.dao.impl.BaseHibernateDaoImpl" abstract="true"> 
     <property name="sessionFactory" ref="expressSessionFactory"/> 
    </bean> 

質問

なぜエラーが発生しますか?それは私のアプリを壊していない、ログレベルはエラーではなく、デバッグです、私のアプリはその後、適切に続行することができます。

設定は正しいですか?

フルXML設定を気にしないでください、何らかの理由で、私はフルXMLとなし、注釈を使用する必要があります。

回答

AOPポイントカット表現の周りいじくる後、私は1つのだけコンテキストを持って、私が書いた簡単なバッチプログラム、に、私はこの問題を持っていないことに気づきました。

これは私の答えにつながります。

私はもともと複数のレイヤーとして私のspring xml設定を構造化しました。

  • トップレベルでは、アプリケーションコンテキストで、すべてのデータソースとトランザクション管理を宣言します。
  • 第2レベルのサーブレットレベルでは、各サーブレットにはそれぞれ独自のコンテキストがあります。このレベルでは、私はすべてのコントローラーサービスDAO構成を入れました。
  • この2番目のレベルのコンテキストが複数存在する必要があります。たとえば、1つのサーブレットコンテキストがすべてのRESTfulサービスを処理する必要があります。もう1つはweb-uiを処理します。

アプリケーションのコンテキストでトランザクション管理の設定を引き継ぐと仮定して構造化しました。 「すべてのサーブレットコンテキストが同じデータソースとトランザクション管理を同じ方法で使用できるように」

しかし、それは分かりません。

データソース設定を含むトランザクション管理項目をサーブレットコンテキスト設定に移動すると、すべて正常に動作し、サービスはトランザクションで正しくラップされます。

ありがとうございました。

答えて

0

エラーは、aopトランザクション構成が正しくないために発生します。スタックトレースのサービスクラスはカバーしません。スタックトレースの取得を停止するまで、マッピングを調整します。可能であれば、注釈付きトランザクション設定を使用する方がよいでしょう。 あなたの2番目の質問への答えは休止テンプレートのソースにある:

try { 
325   session =  getSessionFactory().getCurrentSession(); 
326   } 
327   catch (HibernateException ex) { 
328    logger.debug("Could not retrieve pre-bound Hibernate session", ex); 
329   } 
330   if (session == null) { 
331    session = getSessionFactory().openSession(); 
332    session.setFlushMode(FlushMode.MANUAL); 
333    isNew = true; 
334   } 
+0

「sg.com.diamond.webadmin.service.impl.ClientProfileService」のクラス名とsearchByNameのメソッド名に基づいて、(文字列名)、あなたは私のポイントカット式であるとお考えですか? – p01ntbl4nk

+0

正しい答えを教えてくれました。私は見つけた答えを反映するために質問を更新し、この答えを正しいものとしてマークします。 – p01ntbl4nk

関連する問題