整合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是明智的。
分享到:
相关推荐
2. 在工程内新建class文件, 文件的包起名为ConnectionPool。 3. 依次新建下列文件:ConnectionPool.java、 ConnectionWrapper.java、 LogFile.java、 LogWriter.java、 MakeDateTime.java、 PoolManager.java。 4. ...
- `ConnectionWrapper`:对原始数据库连接进行包装的类,添加额外的功能,如连接池的追踪和管理。 通过分析这个源代码,开发者可以深入理解数据库连接池的工作原理,学习如何实现自定义的数据库连接池,或者根据...
- ConnectionWrapper.java:用于封装数据库连接,提供统一的接口。 - LogFile.java和LogWriter.java:用于日志记录,跟踪连接池的使用情况。 - MakeDateTime.java:处理日期和时间的工具类。 - PoolManager.java...
1. ConnectionWrapper:Druid对JDBC的Connection接口进行了封装,实现了连接池的特性,如连接的获取、释放、检测等。 2. DataSource:作为数据源的核心类,DruidDataSource提供了连接池的初始化、配置以及连接的...
- **ConnectionWrapper类**:包装原始的数据库连接对象,添加额外的监控和管理功能。 - **PoolConfig类**:存储连接池的配置参数,如最大连接数、最小连接数、超时时间等。 - **连接获取方法**(如getConnection())...
- 当需要获取数据库连接时,应通过`ConnectionWrapper`类实现,且使用完毕后记得关闭连接。 - **HQL查询语句问题定位**: - 遇到HQL语法错误时,可访问特定URL(如`http://localhost:8080/ekp/trans/to_sql?hql=你...