2014-02-19 82 views
0

我在版本4.3.1.Final中使用休眠和C3P0。 MySQL 5.6.14(所有表的InnoDB)。在hibernate.cfg.xml休眠:c3p0拋出NullPointerException在NewProxyConnection.commit()

C3P0設置是:

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> 
<property name="hibernate.c3p0.timeout">300</property> 
<property name="hibernate.c3p0.idle_test_period">3000</property> 
<property name="hibernate.c3p0.preferredTestQuery">SELECT 1</property> 
<property name="hibernate.c3p0.minPoolSize">3</property> 
<property name="hibernate.c3p0.maxPoolSize">100</property> 

當我提交例如事務:

public void editCategory(int id, String title) { 
    Transaction tx = getTransaction(); 
    Query q = session.createQuery("FROM Category WHERE id = :id"); 
    q.setInteger("id", id); 
    Category cat = (Category) q.uniqueResult(); 
    cat.setTitle(title); 
    tx.commit(); 
} 
private Transaction getTransaction() { 
    Transaction tx = session.getTransaction(); 
    if (!tx.isActive()) { 
     tx.begin(); 
    } 
    return tx; 
} 

在大約3 5的嘗試提交失敗,因爲:

SEVERE: Servlet.service() for servlet [appserver.services.ApplicationConfig] in context with path [/AppServer] threw exception [org.hibernate.TransactionException: commit failed] with root cause 
java.lang.NullPointerException 
    at com.mchange.v2.c3p0.impl.NewProxyConnection.commit(NewProxyConnection.java:1284) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:112) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:180) 
    at appserver.dao.CategoryDao.createCategory(CategoryDao.java:60) 
    at appserver.services.CategoryResource.createCategory(CategoryResource.java:41) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171) 
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:402) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:349) 
    ... stacktrace continues 

有沒有C3P0的東西我錯過了嗎?感謝幫助!

回答

1

您的應用服務器正在報告造成根本原因的根本原因,即它正在跳過一個會報告更多信息性消息的異常,「您無法在已關閉的連接上運行!!!」

您的應用程序中存在競爭條件。您在摘錄的方法中引用的對象'會話'很可能有時在查詢和提交之間關閉()。 (休眠會話包裝JDBC連接。)

您需要了解會話的生命週期,並確保永不發生。最簡單的,你可以避免緩存會話。你可以在需要的時候獲得它們,並且在你使用之後立即關閉它們,也就是在你提交事務之後(可靠地通過finally塊或try-with-resources構造)。

+0

Steve,謝謝你的回答。我有靜態會話工廠,然後在DAO對象的構造函數中,我初始化字段會話如下:this.session = HibernateUtil.getSessionFactory()。getCurrentSession(); – kamelot

+0

和我有會話上下文類屬性設置爲:線程 kamelot

+0

因此,關於當前會話,在您的配置下獲取與一個線程關聯:誰打開它,誰關閉() es呢?也就是說,據我瞭解(我不是Hibernate專家!),SessionFactory.getCurrentSession()是一個方便,它將獲得一個已經[已經被SessionFactory.openSession()]打開的Session,它已被綁定到一個上下文[在你的情況下是一個線程],所以你不必顯式地將它作爲一個方法參數傳遞。但是你仍然需要openSession(),瞭解它們的生命週期,並且非常重要的是從c3p0的角度來看,close()它們。 –