2012-01-17 144 views
3

我使用hibernate 3.6.7來做映射。我將連接部分設置爲靜態。 我需要服務程序永遠運行,另一個服務將調用此服務的一些方法來查詢數據庫。 當我離開服務運行的第一天,效果很好,但是當我把它的第二天,它提供了:org.hibernate.exception.GenericJDBCException:無法執行查詢

org.hibernate.exception.GenericJDBCException: could not execute query 
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140) 
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
    at org.hibernate.loader.Loader.doList(Loader.java:2545) 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276) 
    at org.hibernate.loader.Loader.list(Loader.java:2271) 
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:459) 
    at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:365) 
    at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196) 
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268) 
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) 
    at com.myCompany.Query.myMethod(Query.java:99) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) 
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:185) 
    at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) 
    at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288) 
    at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) 
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) 
    at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339) 
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) 
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537) 
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 
    at org.ebayopensource.ginger.server.internal.container.MessageProcessor.processRequest(MessageProcessor.java:93) 
    at org.ebayopensource.ginger.server.container.GingerServletShell.service(GingerServletShell.java:80) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) 
    at java.lang.Thread.run(Thread.java:662) 
Caused by: java.sql.SQLException: Closed Connection 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208) 
    at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:864) 
    at oracle.jdbc.driver.PhysicalConnection.prepareStatement(PhysicalConnection.java:783) 
    at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:534) 
    at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:452) 
    at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161) 
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1700) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:801) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274) 
    at org.hibernate.loader.Loader.doList(Loader.java:2542) 

看來連接被關閉。 任何人都可以請給我一些建議嗎?

非常感謝你:)

回答

12

聽起來要麼數據庫已經關閉了連接或一些網絡設備已經終止了插座。有很多方法可以解決此問題:

  1. 您可以在連接上每隔一段時間發一些「keep alive」類型的查詢(例如:SELECT 1)以保持活動狀態。這假定它因爲閒置而關閉。
  2. 您可以經常重新打開連接。
  3. 如果你得到一個連接關閉異常,那麼你可以重新打開連接。咄。
  4. 您可以使用可以爲您保持活動狀態和重新連接的連接池。 Apache's DBCP是許多人的最愛。

我推薦最後一個。你會使用DBCP類似:

BasicDataSource ds = new BasicDataSource(); 
ds.setDriverClassName("oracle.jdbc.driver.OracleDriver"); 
ds.setUsername("scott"); 
ds.setPassword("tiger"); 
ds.setValidationQuery("SELECT 1"); // this is database specific 
ds.setTestWhileIdle(true); // test the connections every so often 
ds.setUrl(connectURI); 
... 
while (!shutdown) { 
    Connection conn = dataSource.getConnection(); 
    Statement stmt = conn.createStatement(); 
    ... 
    stmt.close(); 
    // this returns the connection back to the pool instead of really closing 
    // the connection 
    conn.close(); 
} 

所以不是你通過BasicDataSource周圍,並呼籲getConnection()當你需要連接的Connectionconn.close()周圍路過的時候,你用它做。該池執行所有的驗證工作等。它還將允許多個線程使用數據庫。

希望這會有所幫助。


編輯:也不能舉行hibernate session開了很長一段時間。爲了向您展示該會話應該是多麼短暫,我將引用以下文檔:

會話的生命週期受邏輯事務的開始和結束限制。 (長事務可能跨越多個數據庫事務。)

會話保存數據庫連接,因此您永遠不想將它保留在任何時間長度。您應該執行一些數據庫請求(如帶查詢和更新的單個Web請求),然後關閉會話,以便將基礎數據庫連接返回到池中。

+1

謝謝,但我試圖讓一個活動的線程運行並執行查詢,但它不起作用。我必須每次關閉休眠會話。只有這種方式有效。 – 2012-02-09 21:36:57

+2

哦。我沒有意識到你一直在開一個休眠會話。這是非常糟糕的形式。你應該在你的數據庫通過之後關閉它,否則它將永遠停留在特定的連接上。 – Gray 2012-02-09 21:48:23

+1

我編輯了我的答案,將會話考慮在內。 – Gray 2012-02-09 23:13:36