Hibernate程序使用WAS连接池提交事务时出现 NullPointerException

Hibernate应用程序部署到WebSphere Application Server 5.1上,使用WAS的连接池,程序在处理了比较多的 session.save(object)操作之后,在执行提交事物 trans.commit()之时出现以下异常

 java.lang.NullPointerException
        at oracle.jdbc.dbaccess.DBData.clearItem(DBData.java:431)
        at oracle.jdbc.dbaccess.DBDataSetImpl.clearItem(DBDataSetImpl.java:3528)
        at oracle.jdbc.driver.OraclePreparedStatement.clearParameters(OraclePreparedStatement.java:3401)
        at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.resetStatement(WSJdbcConnection.java:1719)
        at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.prepareStatement(WSJdbcConnection.java:1415)
        at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.prepareStatement(WSJdbcConnection.java:1381)
        at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:497)
        at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:94)
        at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
        at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:218)
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2220)
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2656)
        at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:52)
        at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:28)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)

因为开发用的是Tomcat应用服务器,配置的Tomcat连接池,所以在本地跑怎么操作都不会有这种错误,费了好一翻工夫也没能定位,查错中总是受 java.lang.NullPointerException 的影响,一遍一遍地审视代码,会是哪个变量没有初始化呢?

自我折磨了好一阵子,无奈之时去网上Google一把(其实早该这么做的,也就因为怀疑问题出在自己写的代码),才发现原来别人也遇到过类似的问题, Hibernate的官方论坛也有这种讨论.

http://www.google.cn/search?complete=1&hl=zh-CN&newwindow=1&q=+oracle.jdbc.dbaccess.DBDataSetImpl.clearItem&meta=

网上有说是驱动的问题,有说是Hibernate数据库方言的问题,也有说最大缓存语句的问题

1. Delete Object error http://forum.hibernate.org/viewtopic.php?t=934050
   其中提到的有换 Oracle 数据库驱动, 有人试着换成 ojdcbc14.jar 解决,最后有人说到设置 c3p0 的hibernate.c3p0.max_statements  为 0 就行

2. NullPointerException on transaction.commit() http://forum.hibernate.org/viewtopic.php?t=973414&sid=04bbd1a8951b3051c52e374a7888d35e
   回贴中说是把 org.hibernate.dialect.OracleDialect 换成 org.hibernate.dialect.Oracle9Dialect, 但有人采取这种做法无效,何况我用的还是 8.0.5 的Oracle,I 都不带.

3. WAS 6上DataSource的问题 http://www.itpub.net/743938.html
   这篇贴主就直接撇名了把Data Source的Command Cache只能设为0,一旦大于0就报以上错误,看来这是一个比较明确的解决办法。于是我就在WAS的控制台下把我所用连接池的 语句高速缓存大小 设置为 0 ,然后重启WAS,问题得到解决。就是不知道不缓存 Statement 对性能会产生怎么样的影响,须进一步了解一下。

   我也试过换数据库驱动的办法,把原有的驱动换成在我本地可用的class12.jar包,没有效果。又换成ojdbc.jar包试试,还是没用。

    总结出现以上错误的解决办法,设置WAS的数据源属性的 Command Cache(也就是语句高速缓存大小)为0, 如果用的别的连接池产品,要设置相应的 max_statements 为 0,属性名具体参考对应连接池产品。

    注意,改了WAS的数据源设置需要重启WAS的。

本文链接 https://yanbin.blog/hibernate-was-connection-pool-nullpointerexception/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

10 Comments
Inline Feedbacks
View all comments
狐狸爱做梦
狐狸爱做梦
16 years ago

太感谢了!

隔叶黄莺
16 years ago

在 WAS 下如果用的DBCP作连接池,出现类似下面的错误

2007-12-03 17:43:20,253 ERROR com.tcl.sr3.webapp.action.ActionExceptionHandler - org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: JDBC commit failed Caused by: org.hibernate.TransactionException: JDBC commit failed

at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java(Compiled Code))

at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java(Compiled Code))

at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java(Compiled Code))

..................................................................................................

at com.ibm.ws.http.HttpConnection.readAndHandleRequest(HttpConnection.java(Compiled Code))

at com.ibm.ws.http.HttpConnection.run(HttpConnection.java(Compiled Code))

at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java(Compiled Code)) Caused by: java.sql.SQLException: Io exception: End of TNS data channel

at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)

at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)

at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:333)

at oracle.jdbc.driver.OracleConnection.commit(OracleConnection.java(Compiled Code))

at org.apache.commons.dbcp.DelegatingConnection.commit(DelegatingConnection.java(Compiled Code))

at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.commit(PoolingDataSource.java(Compiled Code))

at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java(Compiled Code))

... 101 more

请设置这两项,也是为了不缓存语句就可解决,用 LoadRunner 做了同时一百个用户的测试通过。

<property name="poolPreparedStatements" value="false"/>

<property name="maxOpenPreparedStatements" value="0"/>

馅饼
馅饼
16 years ago

@隔叶黄莺

关于你写的这个错误:

在 WAS 下如果用的DBCP作连接池,出现类似下面的错误

2007-12-03 17:43:20,253 ERROR com.tcl.sr3.webapp.action.ActionExceptionHandler - org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: JDBC commit failed Caused by: org.hibernate.TransactionException: JDBC commit failed ....

我也出现同样的问题,但是我的环境是ORACLE 9I、Websphere V6,用websphere的jndi。前台是webwork、spring、hibernate,按你的方法在applicationContext.xml中对应的dataSource下增加了你说的两上属性,启动服务运行时,系统提示没有这个属性。

可否给预进一步的提示?谢谢。

spring-1.2.6.jar

webwork-2.1.7.jar

hibernate-3.0.5.jar

oracle的jdbc:ojdbc14.jar

隔叶黄莺
16 years ago

你用的是jndi,就应该到WAS里配置这个 Datasource 的相应属性,把高速缓存语句大小改为0

你在applicationContext.xml中对应的dataSource设置属性时一定要参照你所配置的 Bean 是否有相应的属性才行。

冬天
冬天
16 years ago

@隔叶黄莺

poolPreparedStatements

对应的中文叫什么可以告诉我以下吗?

隔叶黄莺
16 years ago

语句高速缓存大小

松
14 years ago

@隔叶黄莺

你好饿,看到你对于JDBC commit failed .... 的回复, 你解决了吗?

能告诉我下吗? 困扰我好几天了,

906410466 能加我吗,。期待中... 万谢

隔叶黄莺
14 years ago

Hibernate 在事物的过程中会依序把 sql 语句放在 insert/delete/update 容器中,在 commit 时才依次执行它们,所以很多的错误最终可能都引起 JDBC commit faild 错误。应该依据它前面的具体的错误提示来定位具体的原因。

change_self
change_self
13 years ago

那么本质的原因是为什么呢?

隔叶黄莺
13 years ago

@change_self

你也遇到了同样的问题了吗?说真的,还没细究过这其中的原因,以后实际中再重现了类似的问题得找找原由了。