복붙노트

[SPRING] Spring과 Hibernate는 갑자기 트랜잭션을 읽기 전용으로 설정했다.

SPRING

Spring과 Hibernate는 갑자기 트랜잭션을 읽기 전용으로 설정했다.

Spring 2.5.2와 Hibernate 3.2.6.ga를 사용하는 JBoss 4.2.3에서 실행되는 어플리케이션이 있습니다. 이것은 자체 사용자를 사용하여 Linux JEE01 2.6.16.60-0.54.5-smp에서 실행 중입니다. 다른 머신의 Oracle 10G 데이터베이스에 쓰기.

우리는 표준보기 -> 서비스 -> 다오 레이어링을 사용하고 있습니다. 각 DAO에는 @ 리포지토리가 주석으로 표시됩니다.

이것은 많은 문제없이 하루 24 시간 연중 무휴로 운영되지만, 며칠마다, 때로는 하루에 두 번씩 전체 시스템이 더 이상 데이터베이스에 아무 것도 쓸 수없는 나쁜 상태가됩니다. 이러한 스택 추적은 로그에 나타납니다.

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not
      allowed in read-only mode (FlushMode.NEVER/MANUAL): 
Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction
      definition.

우리는 전체 시스템을 스캔했고 flushmode가 일시적으로 MANUAL로 설정되고 그 후에 finally 블록이 원래 값으로 되돌아가는 시스템이 하나 있습니다. 이는이 쿼리를 실행하기 전에 데이터베이스에 상태를 플러시하지 않기 때문입니다. 그래서 우리는 이것을 매우 쉽게 바꿀 수 없습니다. 일반 FlushMode는 AUTO로 설정되어 있으며 여러 곳에서 COMMIT으로 임시 설정하고 다시 기본값으로 다시 전환합니다.

서버 재시작 만이 시스템을 작업 순서로 복원합니다.

질문 : 시스템이 모든 트랜잭션을 읽기 전용 / 수동 플러시 모드로 설정하는 이유는 무엇입니까? 나는 이것을 봤지만 해결책을 찾지 못했습니다.

이것은 우리의 봄과 최대 절전 모드 구성입니다 (관련 부분 만 표시).

     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="dataSource">
   <ref bean="datasourceName" />
  </property>
  <property name="configLocation">
   <value>classpath:hibernate.cfg.xml</value>
  </property>
 </bean>

 <bean id="hibernateInterceptor"
  class="org.springframework.orm.hibernate3.HibernateInterceptor">
  <property name="sessionFactory" ref="sessionFactory" />
 </bean>

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

 <tx:advice id="txAdvice" transaction-manager="txManager" >
  <!-- the transactional semantics... -->
  <tx:attributes >
   <!-- all methods starting with 'get' are read-only -->
   <tx:method name="approve*" read-only="false"
    propagation="REQUIRED" rollback-for="java.lang.Exception" />
   <tx:method name="update*" read-only="false"   
    propagation="REQUIRED" rollback-for="java.lang.Exception"/>
   <tx:method name="save*" read-only="false"
    propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="delete*" read-only="false"
    propagation="REQUIRED" rollback-for="java.lang.Exception" />
   <!-- other methods use the default transaction settings (see below) -->
   <tx:method name="*" read-only="true" propagation="REQUIRED" />
  </tx:attributes>
 </tx:advice>

 <aop:config>
  <aop:pointcut id="serviceMethods"
   expression="execution(* com.myapplication.service.*.*(..))"  />
  <aop:advisor advice-ref="txAdvice" 
   pointcut-ref="serviceMethods" />
 </aop:config>

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

-- end of spring config --

-- hibernate configuation --
<hibernate-configuration>
    <session-factory name="">
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <property name="show_sql">false</property>
        <property name="use_outer_join">false</property>
        <property name="hibernate.cache.use_query_cache">true</property>
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <property name="hibernate.connection.SetBigStringTryClob">true</property>
        <property name="hibernate.jdbc.batch_size">0</property>
    </session-factory>
    <mapping ----/>
</hibernate-configuration>

다음은 스택 추적입니다.

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
at org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1137)
at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:701)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:699)
at nl.company.myapp.dao.impl.GenericDAOImpl.save(GenericDAOImpl.java:94)
at nl.company.myapp.dao.impl.CallDAOImpl.save(CallDAOImpl.java:266)
at nl.company.myapp.dao.impl.CallDAOImpl.save(CallDAOImpl.java:47)
at nl.company.myapp.service.impl.CallServiceImpl.saveCall(CallServiceImpl.java:98)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy142.saveCall(Unknown Source)
at nl.company.myapp.view.bean.call.CallDetailBean.doSave(CallDetailBean.java:319)
at nl.company.myapp.view.bean.EditModeAwareBean.save(EditModeAwareBean.java:151)
at sun.reflect.GeneratedMethodAccessor472.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.apache.el.parser.AstValue.invoke(AstValue.java:131)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
at org.apache.myfaces.trinidad.component.MethodExpressionMethodBinding.invoke(MethodExpressionMethodBinding.java:46)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at org.apache.myfaces.trinidad.component.UIXCommand.broadcast(UIXCommand.java:190)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:458)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:763)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at nl.company.myapp.view.audit.AuditFilter.doFilter(AuditFilter.java:88)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._invokeDoFilter(TrinidadFilterImpl.java:238)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:195)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:138)
at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:124)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:437)
at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:366)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Thread.java:595)

이 모두 잘 작동합니다.

해결법

  1. ==============================

    1.이 예외는 Spring의 HibernateTemplate 클래스에있는 다음 코드에서 유래한다.

    이 예외는 Spring의 HibernateTemplate 클래스에있는 다음 코드에서 유래한다.

    protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {
        if (isCheckWriteOperations() && getFlushMode() != FLUSH_EAGER &&
                session.getFlushMode().lessThan(FlushMode.COMMIT)) {
            throw new InvalidDataAccessApiUsageException(
                    "Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): "+
                    "Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.");
        }
    }
    

    이 수표의 근거는 다음과 같이 설명됩니다.

    이것들 중 어떤 것도 종을 울리니?

    코드 또는 Spring ORM에 버그가있을 수 있습니다. 이 검사를 비활성화하려면 setCheckWriteOperations (false)를 호출하면됩니다.

  2. ==============================

    2.aseesing, 귀하의 구성을 확인하십시오. 봄 컨텍스트 부분에서는

    aseesing, 귀하의 구성을 확인하십시오. 봄 컨텍스트 부분에서는

    <!-- other methods use the default transaction settings (see below) -->
       <tx:method name="*" read-only="true" propagation="REQUIRED" />
    

    일반적으로 일부 액세스 만 get / find / query와 같은 읽기 전용 유형입니다.

    <!--default is required transaction-->
    <tx:method name="*"/>
    

    또 다른 것은, opensessioninview 패턴을 사용합니까? 플러시 모드는 오픈시 스템에서 올바르게 설정 될 수 있습니다. web.xml에서 필터를 사용하거나 응용 프로그램 컨텍스트 config에서 spring 인터셉터를 사용할 수 있습니다.

  3. ==============================

    3.당신의 web.xml에 넣어 :

    당신의 web.xml에 넣어 :

    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>flushMode</param-name>
            <param-value>AUTO</param-value>
        </init-param>
    </filter>
    
  4. ==============================

    4.내 추측은 이것이 당신을 위해하는 봄이라는 것입니다. Spring에서 OpenSessionInViewFilter에 의해 수행되는 것을 기억하는 것 같습니다. 당신이 사용하고 있습니까?

    내 추측은 이것이 당신을 위해하는 봄이라는 것입니다. Spring에서 OpenSessionInViewFilter에 의해 수행되는 것을 기억하는 것 같습니다. 당신이 사용하고 있습니까?

  5. ==============================

    5.이것은 메모리에 있으므로 매우 자세하지 않습니다. flushmode를 설정하는 두 가지 방법이 있습니다. 나는 봄 길과 최대 절전 모드라고 생각한다. 우리는 (Spring?) 방식을 한 번만 사용하고 Hibernate 방식을 사용하기 때문에 Hibernate의 내부 상태를 어떻게 든 잘못되게 만들었습니다. 어느 것이 내 문제를 만든거야. 우리가 모든 것을 일치 시켰을 때 문제는 사라졌습니다.

    이것은 메모리에 있으므로 매우 자세하지 않습니다. flushmode를 설정하는 두 가지 방법이 있습니다. 나는 봄 길과 최대 절전 모드라고 생각한다. 우리는 (Spring?) 방식을 한 번만 사용하고 Hibernate 방식을 사용하기 때문에 Hibernate의 내부 상태를 어떻게 든 잘못되게 만들었습니다. 어느 것이 내 문제를 만든거야. 우리가 모든 것을 일치 시켰을 때 문제는 사라졌습니다.

  6. ==============================

    6.1 bean에서 2 개의 "baseTransactionProxy"를 사용했을 때이 문제가 발생했습니다.

    1 bean에서 2 개의 "baseTransactionProxy"를 사용했을 때이 문제가 발생했습니다.

    첫 번째 :

    <bean id="generalDao" parent="baseTransactionProxy">
        <property name="target">
            <bean class="com...GeneralDao" parent="baseDAO" />
        </property>
    </bean>
    

    둘째 :

    <bean id="ruleDao" parent="baseTransactionProxy">
        <property name="target">
            <bean class="com...RuleDao" parent="baseDAO">
                <constructor-arg ref="generalDao"></constructor-arg>
            </bean>
        </property>
    </bean>
    

    우리가 한

    class ruleDao{
        generalDao.generalSaveOrUpdateAll(hbms); // OK HERE
        saveOrUpdateAll(otherHbms); //Exception here
    }
    

    도움이되는지 확실하지 않지만 동일한 프록시 호출에서 2 개의 다른 "baseTransactionProxy"를 혼합하는 것이 좋지 않은 것 같습니다.

  7. ==============================

    7.구현에서 실행 pointcut을 사용하고 있으며 일반적인 DAO를 사용하고 있기 때문에 예상대로 트랜잭션을 처리하지 못하고 있으며 이는 실제 문제의 징후 일뿐입니다.

    구현에서 실행 pointcut을 사용하고 있으며 일반적인 DAO를 사용하고 있기 때문에 예상대로 트랜잭션을 처리하지 못하고 있으며 이는 실제 문제의 징후 일뿐입니다.

    Spring이 호출 할 때 DAO를 프록시하고 있는지 확인하십시오. 일반 DAO에 적절한 트랜잭션을 사용하려면 대상 (beanid) 구문을 사용해야 할 수도 있습니다.

  8. from https://stackoverflow.com/questions/4448520/spring-and-hibernate-suddenly-set-the-transaction-to-readonly by cc-by-sa and MIT license