2014-04-15 1 views
1

다중 EAR 컨텍스트에서 Spring JTA + Hibernate를 사용할 때 문제가 발생합니다.다중 EAR 컨텍스트에서 예상치 못한 수의 Hibernate 세션이 생성되었습니다.

우리는 (@Transactional을 사용하여) 여러 트랜잭션 서비스를 제공합니다. 우리의 서비스는 DAO에 대한 참조가있는 POJO입니다. 또한 여러 지속성 단위가 있습니다. 간단하게하기 위해 각 서비스/DAO가 고유 한 PU를 사용한다고 가정합니다. 서비스 2에

  • 통화는 통화 당 새로운 최대 절전 모드 세션을 생성합니다 : EAR1의 서비스 1 트랜잭션을 시작하고 EAR2에서 여러 번 서비스 2를 호출하면

    .

  • 모든 세션은 트랜잭션이 끝날 때 (즉, Service1 호출이 완료되고 트랜잭션을 커밋 할 때) 플러시/커밋됩니다. -

중요 사항 : 봄과 최대 절전 모드는 루트 클래스 로더에 의해로드되지 않고 EAR 클래스 로더에 의해로드됩니다. 이것은 Spring과 Hibernate 클래스가 EAR 당 한 번로드된다는 것을 의미합니다.

코드 및 디버깅을 살펴보면 문제가 스레드 로컬 동기화 (즉, TransactionSynchronizationManager 클래스)에서 비롯된 것으로 생각됩니다. 어떻게됩니까 은 다음과 같습니다

  • 트랜잭션은 서비스 2도 TransactionAspectSupport가 호출되는 서비스 2 방법 주위에서 개막 거래되기 때문에
  • 서비스 1은
  • EAR2
  • 에서 서비스 2를 호출 EAR1에서 서비스 1에 의해 시작됩니다.
  • 길 아래로 EntityManagerFactoryUtils는 EntityManager가 TransactionSynchronizationManager에 등록되어 있는지 확인합니다. 이것은 SharedEntityManagerCreator가 EntityManagerFactoryUtils.doGetTransactionalEntityManager()를 호출 할 때 발생합니다. 아래의 호출 스택 1을 참조하십시오.
  • 등록 된 EntityManager가 없기 때문에 새로운 EntityManager 및 새로운 최대 절전 모드 세션을 생성합니다. 아래의 호출 스택 2를 참조하십시오.
  • Service2 호출에서 복귀 할 때 동기화는 새로운 것으로 간주되기 때문에 제거됩니다. 이는 TransactionAspectSupport.commitTransactionAfterReturning()에서 발생합니다. 아래의 호출 스택 3을 참조하십시오.
  • Service2에 대한 후속 호출은 새 엔티티 관리자 + 세션 + 동기화를 다시 만드는 과정을 반복합니다.

모든 세션도 글로벌 트랜잭션에 등록되므로 모두 해당 트랜잭션이 끝날 때 플러시/커밋됩니다. 부작용은 Service2에 대한 호출이 동일한 엔티티를 수정하면 해당 엔티티가 RDBMS에 여러 번 저장된다는 것입니다 (즉 여러 개의 동일한 업데이트 쿼리가 실행 됨).

같은 EAR 수익률에 배포 서비스 1와 서비스 2 모두 같은 시나리오 완전히 다른 결과 :

  • 하나 개의 최대 절전 모드 세션은 고유 한 세션이 트랜잭션의 끝에서 플러시되는 것을
  • 을 생성 (하고 단일 업데이트 쿼리가 실행 됨)

일부 시나리오에서는 잠시 동안 수백 개의 세션이 생성되어 성능 문제가 발생합니다.

Spring과 Hibernate를 루트 ClassLoader로 옮겨서 문제를 해결할 수 있지만 그것이 적절하지 않을 수도 있습니다. 두 개의 EAR이 별도의 JVM에 배포되면 어떻게됩니까? ClassLoader 계층에서 스프링을 이동하고 최대 절전 모드로 설정하면 Spring 컨텍스트 설정이 심각하게 손상됩니다.

스프링 트랜잭션의 예상되는 동작입니까? 스레드 로컬 동기화를 피하고 트랜잭션 동기화를 사용할 수 있습니까? 우리가 달성하고자하는 것에 관해서 우리의 설정 (아래 참조)이 잘못 되었습니까?

우리가 사용하는 : 봄 버전 : 3.2.8.RELEASE 최대 절전 모드 버전 : 4.1.12.Final

는 여기에 우리의 봄 설정의 몇 가지 관련 조각입니다

<tx:jta-transaction-manager /> 

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
     abstract="true"> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="database" value="${jpa.database}" /> 
       <property name="generateDdl" value="${jpa.generateDdl}" /> 
       <property name="showSql" value="true" /> 
      </bean> 
     </property> 
     <property name="dataSource" ref="coreDataSource" /> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
       <prop key="hibernate.transaction.jta.platform">${jpa.transaction.jta.platform}</prop> 
       <prop key="hibernate.jdbc.wrap_result_sets">${jpa.wrap_result_sets}</prop> 
       <prop key="hibernate.generate_statistics">${jpa.generateStatistics}</prop> 
       <prop key="hibernate.cache.region.factory_class">${jpa.cache.factory_class}</prop> 
       <prop key="hibernate.cache.use_second_level_cache">true</prop> 
       <prop key="hibernate.cache.use_query_cache">true</prop> 
       <prop key="hibernate.format_sql">${jpa.formatSql}</prop> 
       <prop key="hibernate.use_sql_comments">${jpa.useSqlComments}</prop> 
      </props> 
     </property> 
    </bean> 

JPA를. 우리의 DAO transaction.jta.platform = org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform

<bean id="referentialCoreEntityManagerFactory" parent="entityManagerFactory"> 
    <property name="persistenceXmlLocation" value="classpath:META-INF/referential-core-persistence.xml" /> 
    <property name="persistenceUnitName" value="referential-core" /> 
</bean> 

<?xml version="1.0" encoding="UTF-8"?> 
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" 
     version="1.0"> 

    <persistence-unit name="referential-core" transaction-type="JTA" /> 

</persistence> 

기본 클래스 기업의 관리자가 정의되는 방법을 보여주는 :

public abstract class BaseDAO<E extends IBaseEntity> extends com.sungard.decalog.framework.domain.dao.jpa.BaseDAO<E> { 

    private EntityManager entityManager; 

    /** 
    * @param entityClass 
    */ 
    public <U extends E> BaseDAO(Class<U> entityClass) { 
     super(entityClass); 
    } 

    @Override 
    protected final EntityManager getEntityManager() { 
     return entityManager; 
    } 

    @PersistenceContext(unitName = "referential-core") 
    public void setEntityManager(EntityManager entityManager) { 
     this.entityManager = entityManager; 
    } 

} 

호출 스택 1 : 신규의 EntityManager의 제작 및 세션 :

Daemon Thread [[ACTIVE] ExecuteThread: '15' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 239 in SessionImpl)) 
-> SessionImpl.<init>(Connection, SessionFactoryImpl, SessionOwner, TransactionCoordinatorImpl, boolean, long, Interceptor, boolean, boolean, ConnectionReleaseMode, String) line: 239 
    SessionFactoryImpl$SessionBuilderImpl.openSession() line: 1597 
    EntityManagerImpl.getRawSession() line: 121 
    EntityManagerImpl.getSession() line: 97 
    EntityManagerImpl(AbstractEntityManagerImpl).joinTransaction(boolean) line: 1207  
    EntityManagerImpl(AbstractEntityManagerImpl).postInit() line: 178 
-> EntityManagerImpl.<init>(EntityManagerFactoryImpl, PersistenceContextType, PersistenceUnitTransactionType, boolean, Class, Map) line: 89  
    EntityManagerFactoryImpl.createEntityManager(Map) line: 179 
    EntityManagerFactoryImpl.createEntityManager() line: 174  
    GeneratedMethodAccessor450.invoke(Object, Object[]) line: not available 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    LocalContainerEntityManagerFactoryBean(AbstractEntityManagerFactoryBean).invokeProxyMethod(Method, Object[]) line: 376 
    AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(Object, Method, Object[]) line: 519  
    $Proxy116.createEntityManager() line: not available 
-> EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactory, Map) line: 202 
    SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(Object, Method, Object[]) line: 211 
    $Proxy118.find(Class, Object) line: not available 
    GenericLoaderCodifDAO(BaseDAO<E>).findById(Serializable) line: 57 
    GenericLoaderCodifService.findGenericLoaderCodif(String, String, String) line: 18 
    ReferentialFacade.findGenericLoaderCodif(String, String, String) line: 161 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317 
    ReflectiveMethodInvocation.invokeJoinpoint() line: 183 
    ReflectiveMethodInvocation.proceed() line: 150 
    TransactionInterceptor$1.proceedWithInvocation() line: 96 
    TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method, Class, TransactionAspectSupport$InvocationCallback) line: 260 
    TransactionInterceptor.invoke(MethodInvocation) line: 94  
    ReflectiveMethodInvocation.proceed() line: 172 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204 
    $Proxy124.findGenericLoaderCodif(String, String, String) line: not available  
    ReferentialFacadeBean_590diy_Impl(ReferentialFacadeBean).findGenericLoaderCodif(String, String, String) line: 271 
    ReferentialFacadeBean_590diy_EOImpl.__WL_invoke(Object, Object[], int) line: not available 
    SessionRemoteMethodInvoker.invoke(BaseRemoteObject, MethodDescriptor, Object[], int, String, Class<?>) line: 40 
    ReferentialFacadeBean_590diy_EOImpl.findGenericLoaderCodif(String, String, String) line: not available 
    ReferentialFacadeBean_590diy_EOImpl_WLSkel.invoke(int, Object[], Object) line: not available  
    ServerRequest.sendReceive() line: 174 
    ClusterableRemoteRef.invoke(RemoteReference, RuntimeMethodDescriptor, Object[], Method) line: 345 
    ClusterableRemoteRef.invoke(Remote, RuntimeMethodDescriptor, Object[], Method) line: 259  
    ReferentialFacadeBean_590diy_EOImpl_1036_WLStub.findGenericLoaderCodif(String, String, String) line: not available 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    RmiClientInterceptorUtils.invokeRemoteMethod(MethodInvocation, Object) line: 116  
    SimpleRemoteStatelessSessionProxyFactoryBean(SimpleRemoteSlsbInvokerInterceptor).doInvoke(MethodInvocation) line: 99  
    SimpleRemoteStatelessSessionProxyFactoryBean(AbstractRemoteSlsbInvokerInterceptor).invokeInContext(MethodInvocation) line: 141 
    SimpleRemoteStatelessSessionProxyFactoryBean(AbstractSlsbInvokerInterceptor).invoke(MethodInvocation) line: 189 
    ReflectiveMethodInvocation.proceed() line: 172 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204 
    $Proxy314.findGenericLoaderCodif(String, String, String) line: not available  
    ReferentialService.findGenericLoaderCodif(String, String, String) line: 54 
    SessionService.refreshSession(ISessionContext, ISessionSnapshot, ISessionData) line: 1114 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 198 
    $Proxy357.refreshSession(ISessionContext, ISessionSnapshot, ISessionData) line: not available 
    SessionFacadeService.loadSession(ISessionContext, ISessionSnapshot, ISessionData, ReloadSession) line: 880 
    SessionFacadeService.loadSession(long, ReloadSession) line: 848 
    ... 
    <snip> 

호출 스택 2 : 새롭게 생성 EntityManager의 동기화 등록 :

Daemon Thread [[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended) 
    TransactionSynchronizationManager.registerSynchronization(TransactionSynchronization) line: 289 
    EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactory, Map) line: 211 
    SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(Object, Method, Object[]) line: 211 
    $Proxy118.find(Class, Object) line: not available 
    GenericLoaderCodifDAO(BaseDAO<E>).findById(Serializable) line: 57 
    GenericLoaderCodifService.findGenericLoaderCodif(String, String, String) line: 18 
    ReferentialFacade.findGenericLoaderCodif(String, String, String) line: 161 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317 
    ReflectiveMethodInvocation.invokeJoinpoint() line: 183 
    ReflectiveMethodInvocation.proceed() line: 150 
    TransactionInterceptor$1.proceedWithInvocation() line: 96 
    TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method, Class, TransactionAspectSupport$InvocationCallback) line: 260 
    TransactionInterceptor.invoke(MethodInvocation) line: 94  
    ReflectiveMethodInvocation.proceed() line: 172 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204 
    $Proxy124.findGenericLoaderCodif(String, String, String) line: not available  
    ReferentialFacadeBean_590diy_Impl(ReferentialFacadeBean).findGenericLoaderCodif(String, String, String) line: 271 
    ReferentialFacadeBean_590diy_EOImpl.__WL_invoke(Object, Object[], int) line: not available 
    SessionRemoteMethodInvoker.invoke(BaseRemoteObject, MethodDescriptor, Object[], int, String, Class<?>) line: 40 
    ReferentialFacadeBean_590diy_EOImpl.findGenericLoaderCodif(String, String, String) line: not available 
    ReferentialFacadeBean_590diy_EOImpl_WLSkel.invoke(int, Object[], Object) line: not available  
    ServerRequest.sendReceive() line: 174 
    ClusterableRemoteRef.invoke(RemoteReference, RuntimeMethodDescriptor, Object[], Method) line: 345 
    ClusterableRemoteRef.invoke(Remote, RuntimeMethodDescriptor, Object[], Method) line: 259  
    ReferentialFacadeBean_590diy_EOImpl_1036_WLStub.findGenericLoaderCodif(String, String, String) line: not available 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    RmiClientInterceptorUtils.invokeRemoteMethod(MethodInvocation, Object) line: 116  
    SimpleRemoteStatelessSessionProxyFactoryBean(SimpleRemoteSlsbInvokerInterceptor).doInvoke(MethodInvocation) line: 99  
    SimpleRemoteStatelessSessionProxyFactoryBean(AbstractRemoteSlsbInvokerInterceptor).invokeInContext(MethodInvocation) line: 141 
    SimpleRemoteStatelessSessionProxyFactoryBean(AbstractSlsbInvokerInterceptor).invoke(MethodInvocation) line: 189 
    ReflectiveMethodInvocation.proceed() line: 172 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204 
    $Proxy314.findGenericLoaderCodif(String, String, String) line: not available  
    ReferentialService.findGenericLoaderCodif(String, String, String) line: 54 
    SessionService.refreshSession(ISessionContext, ISessionSnapshot, ISessionData) line: 1114 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 198 
    $Proxy357.refreshSession(ISessionContext, ISessionSnapshot, ISessionData) line: not available 
    SessionFacadeService.loadSession(ISessionContext, ISessionSnapshot, ISessionData, ReloadSession) line: 880 
    SessionFacadeService.loadSession(long, ReloadSession) line: 848 
    ... 
    <snip> 

호출 스택 3 : EntityManager 동기화 지우기 (Service2 호출마다 새 호출이 생성됨) :

Daemon Thread [[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended) 
    TransactionSynchronizationManager.clearSynchronization() line: 328 
    TransactionSynchronizationManager.clear() line: 464 
    WebLogicJtaTransactionManager(AbstractPlatformTransactionManager).cleanupAfterCompletion(DefaultTransactionStatus) line: 1006 
    WebLogicJtaTransactionManager(AbstractPlatformTransactionManager).processCommit(DefaultTransactionStatus) line: 805 
    WebLogicJtaTransactionManager(AbstractPlatformTransactionManager).commit(TransactionStatus) line: 724 
    TransactionInterceptor(TransactionAspectSupport).commitTransactionAfterReturning(TransactionAspectSupport$TransactionInfo) line: 475  
    TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method, Class, TransactionAspectSupport$InvocationCallback) line: 270 
    TransactionInterceptor.invoke(MethodInvocation) line: 94  
    ReflectiveMethodInvocation.proceed() line: 172 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204 
    $Proxy124.findGenericLoaderCodif(String, String, String) line: not available  
    ReferentialFacadeBean_590diy_Impl(ReferentialFacadeBean).findGenericLoaderCodif(String, String, String) line: 271 
    ReferentialFacadeBean_590diy_EOImpl.__WL_invoke(Object, Object[], int) line: not available 
    SessionRemoteMethodInvoker.invoke(BaseRemoteObject, MethodDescriptor, Object[], int, String, Class<?>) line: 40 
    ReferentialFacadeBean_590diy_EOImpl.findGenericLoaderCodif(String, String, String) line: not available 
    ReferentialFacadeBean_590diy_EOImpl_WLSkel.invoke(int, Object[], Object) line: not available  
    ServerRequest.sendReceive() line: 174 
    ClusterableRemoteRef.invoke(RemoteReference, RuntimeMethodDescriptor, Object[], Method) line: 345 
    ClusterableRemoteRef.invoke(Remote, RuntimeMethodDescriptor, Object[], Method) line: 259  
    ReferentialFacadeBean_590diy_EOImpl_1036_WLStub.findGenericLoaderCodif(String, String, String) line: not available 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    RmiClientInterceptorUtils.invokeRemoteMethod(MethodInvocation, Object) line: 116  
    SimpleRemoteStatelessSessionProxyFactoryBean(SimpleRemoteSlsbInvokerInterceptor).doInvoke(MethodInvocation) line: 99  
    SimpleRemoteStatelessSessionProxyFactoryBean(AbstractRemoteSlsbInvokerInterceptor).invokeInContext(MethodInvocation) line: 141 
    SimpleRemoteStatelessSessionProxyFactoryBean(AbstractSlsbInvokerInterceptor).invoke(MethodInvocation) line: 189 
    ReflectiveMethodInvocation.proceed() line: 172 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 204 
    $Proxy314.findGenericLoaderCodif(String, String, String) line: not available  
    ReferentialService.findGenericLoaderCodif(String, String, String) line: 54 
    SessionService.refreshSession(ISessionContext, ISessionSnapshot, ISessionData) line: 1114 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] 
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 
    Method.invoke(Object, Object...) line: 597 
    AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317 
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 198 
    $Proxy357.refreshSession(ISessionContext, ISessionSnapshot, ISessionData) line: not available 
    SessionFacadeService.loadSession(ISessionContext, ISessionSnapshot, ISessionData, ReloadSession) line: 880 
    SessionFacadeService.loadSession(long, ReloadSession) line: 848 
    ... 
    <snip> 
+0

제 생각에 문제는 사용했던 아키텍처/디자인이 상당히 끔찍하다고 생각합니다. 당신은 2 가지 매우 나쁜 습관 (데이터베이스 공유와 개체의 소유)을 언급했습니다. 각 EAR은 도메인 (도메인 객체 및 db 스키마가있는 도메인 그룹)을 소유해야하며 다른 응용 프로그램 (또는 EAR)은 해당 데이터에 직접 액세스해서는 안되며 EAR이 소유하고 노출하는 API를 통해서만 가져와야합니다. 항아리를 움직여서 무엇인가 고치려고하지 마십시오. 먼저 아키텍처를 수정하십시오. – Augusto

+0

제 질문은 좋은 디자인이나 나쁜 디자인 또는 하나 이상의 EAR을 갖는 것과 관련이있는 것이 아닙니다. 제가 생각하기에 봄과 최대 절전 모드에서의 문제는 여러 개의 EAR에 걸친 JTA 트랜잭션을 처리하는 것입니다. 완전히 이해할 수있는 것은 더 복잡한 사용 사례 중 하나이므로 가능하면 피해야합니다. 문제의 요점은 아키텍처를 수정하지 않고도 솔루션을 찾는 것입니다. –

답변

0

공유 클래스 로더를 사용하지 않으려면 응용 프로그램간에 실수로 공유되는 정적 변수 문제가 발생할 수 있습니다.

예를 들어 정적 로거가 공유되므로 한 응용 프로그램에서 추적 디버그를 설정하면 다른 응용 프로그램의 속도가 느려지는 것을 볼 수 있습니다. 이것은 공유 클래스 로더가 의도하지 않은 부작용을 일으킬 수있는 예일뿐입니다.

비슷한 것은 Spring이나 Hibernate에서 반드시 그런 것은 아니지만 그들이 사용하는 일부 전이 의존성에서 일어날 수 있으며, 대부분의 라이브러리는 애플리케이션 클래스 로더 레벨에서 전개 될 예정이다.

현재 스프링 클래스와 하이버 네이트를 공유 클래스 로더에 두는 것은별로 좋은 이유가 없으며, 다른 것들과 비교하여 메모리를 거의 소비하지 않습니다.

저는 개인적으로 Spring과 Hibernate를 JVM으로 옮겨가는 대신에 Spring과 Hibernate를 넣을 것입니다. 이것은 실제로 애플리케이션을 재배포 할 수 없게 만들 것이고 공유 라이브러리의 사용을 최소한으로 줄이려고 할 것입니다.

또한 일반적으로 EAR 호출이 필요하지 않지만 복잡한 모델로 인해 포기한 프로그래밍 모델입니다. 일반적인 솔루션은 서비스/DAO 계층을 별도의 jar로 제공하고 jar를 두 응용 프로그램에 배포하는 것입니다. 그런 다음 응용 프로그램 코드는 다른 EAR에 대한 호출이 필요없이 직접 서비스 계층을 호출 할 수 있습니다.

tx:jta-transaction-manager에 의해 자동 감지 된 원시 트랜잭션 관리자는 더 이상 필요하지 않으며 JpaTransactionManager 또는 HibernateTransactionManager과 같은 것으로 대체 될 수 있습니다.

+0

자세한 답변을 보내 주셔서 감사합니다. 우리는 실제로 우리 제품에 두 가지 접근법을 가지고 있습니다. 하나의 "공유 된"귀에 배치 된 모든 귀 및 서비스 + DAO에 동일한 서비스 + DAO가 배치되었습니다. 문제는 전자의 경우에만 나타납니다;). 즉, 현재 아키텍처는 14 세입니다 ... 우리는 그것을 단순화하고 여러 귀를 제거 할 수있는 기회를 기다리고 있습니다 (그러나 기회의 창은 아직 열리지 않았습니다). –

관련 문제