ConnectionWrapper is not visible from class loader

 

    整合Spring DM(OSGi) 和 Hibernate 时出现了一些异常:
java.lang.IllegalArgumentException: interface org.hibernate.jdbc.ConnectionWrapper is not visible from class loader
    at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
    at org.hibernate.jdbc.BorrowedConnectionProxy.generateProxy(BorrowedConnectionProxy.java:91)
    at org.hibernate.jdbc.ConnectionManager.borrowConnection(ConnectionManager.java:186)
    at org.hibernate.jdbc.JDBCContext.borrowConnection(JDBCContext.java:134)
    at org.hibernate.impl.SessionImpl.connection(SessionImpl.java:386)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:507)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:336)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:102)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
 
      第一感觉这个异常是因为OSGi中的Class Loader的问题引起的,但跟踪code发现这个问题并不完全是因为Class Loader的问题。将Hibernate的hibernate.connection.release_mode propertie修改为after_transaction可以解决这个问题。

      但这个问题的根源在哪里呢?
 
    首先我来看看 HibernateTransactionManager.doBegin() 方法中的:
         ......
         if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
               // We're allowed to change the transaction settings of the JDBC Connection.
               //从Thread stack可以看到代码进入了这一行,也就是上面方法返回了true。
               Connection con = session.connection();
                ......
 

   
     isSameConnectionForEntireSession() 方法:
       
protected boolean isSameConnectionForEntireSession(Session session) {
             if (!(session instanceof SessionImpl)) {
                 // The best we can do is to assume we're safe.
                 return true;
             }
             ConnectionReleaseMode releaseMode = ((SessionImpl) session).getConnectionReleaseMode();
             //返回true,所以 releaseMode == ON_CLOSE
             return ConnectionReleaseMode.ON_CLOSE.equals(releaseMode);
         }
 
    但是是什么决定releaseMode呢?
    进一步跟踪发现releaseMode是Hibernate SessionFactory在创建Session的时候传入的,但SessionFactory中的
releaseMode 又是从哪来的呢?原来在 Spring中如果 hibernate.connection.release_mode设置成默认值auto时,在 transaction模式下会读取SpringTransactionFactory的getDefaultReleaseMode值 ON_CLOSE,参考:
   
            // Sets connection release mode "on_close" as default.
           // <p>This was the case for Hibernate 3.0; Hibernate 3.1 changed
           // it to "auto" (i.e. "after_statement" or "after_transaction").
           // However, for Spring's resource management (in particular for
           // HibernateTransactionManager), "on_close" is the better default.
            public ConnectionReleaseMode getDefaultReleaseMode() {
                 return ConnectionReleaseMode.ON_CLOSE;
           }
  因此,Hibernate使用默认的hibernate.connection.release_mode 设置'auto'时Session的Release Mode是ON_CLOSE。而在Transaction模式下明显是不对的,因此在properties中明确指定release_mode为 after_transaction是明智的。




你可能感兴趣的:(java,spring,AOP,Hibernate,osgi)