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的。