2016-08-29 3 views
2

spring-mvc, spring-security, spring-core 및 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 레벨

이 I는 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 컨텍스트가 내가 쓴 간단한 배치 프로그램에, 나는이 문제가없는 것으로 나타났습니다.

이것은 대답으로 연결됩니다.

원래 스프링 세트를 여러 레이어로 구성했습니다.

  • 최상위 레벨에서 응용 프로그램 컨텍스트에서 모든 데이터 소스와 트랜잭션 관리를 선언합니다.
  • 두 번째 레벨 인 서블릿 레벨에서 각 서블릿에는 고유 한 컨텍스트가 있습니다.이 수준에서 모든 컨트롤러 서비스 DAO 구성을 배치합니다.
  • "2 차 레벨"컨텍스트가 여러 개 있어야합니다. 예를 들어, 하나의 서블릿 컨텍스트가 모든 RESTful 서비스를 처리해야하며, 다른 하나는 web-ui를 처리해야합니다.

응용 프로그램 컨텍스트에서 트랜잭션 관리 설정을 사용한다고 가정하고 구조화했습니다. "모든 서블릿 컨텍스트가 동일한 데이터 소스와 트랜잭션 관리를 같은 방식으로 사용할 수 있어야합니다."

하지만 밝혀진 바와 같이.

데이터 소스 구성을 포함하여 트랜잭션 관리 부분을 서블릿 컨텍스트 구성으로 이동하면 모두 제대로 작동하고 트랜잭션이 트랜잭션으로 올바르게 래핑됩니다.

감사합니다.

답변

0

오류는 aop 트랜잭션 구성이 올바르지 않기 때문에 발생합니다. 스택 추적에서 서비스 클래스를 다루지는 않습니다. 스택 추적을 중지 할 때까지 매핑을 조정하십시오. 가능하면 어노테이션 된 트랜잭션 구성을 사용하는 것이 좋습니다. 두 번째 질문에 대한 대답은 최대 절전 모드 템플릿의 소스에 있습니다 searchByName의 "sg.com.diamond.webadmin.service.impl.ClientProfileService"및 방법 이름의 클래스 이름을 기반으로

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

(문자열 이름), 당신은 내 pointcut 표현으로 무엇을 제안하겠습니까? – p01ntbl4nk

+0

정답을 가르쳐 주셨습니다. 내가 찾은 답을 반영하도록 질문을 업데이트 할 것이고 나는이 답을 옳은 것으로 표시 할 것입니다. – p01ntbl4nk

관련 문제