Pregunta

I am using both Hibernate and C3P0 in version 4.3.1.Final. MySQL 5.6.14 (InnoDB for all tables).

C3P0 settings in hibernate.cfg.xml are:

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

When I commit a transaction for example:

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;
}

In approximately 3 of 5 attempts commit fails because of:

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

Is there something with C3P0 settings that I'm missing? Thanks for help!

¿Fue útil?

Solución

Your app server is reporting the root cause of the root cause, that is it is skipping an Exception that would have reported the more informative message, "You can't operate on a closed Connection!!!"

You have a race condition in your application. The Object 'session' referenced in the methods you excerpt is very likely sometimes close()ed between the query and the commit. (The hibernate Session wraps the JDBC Connection.)

You need to understand the lifecycle of your Sessions, and ensure that this never happens. Most simply, you might avoid caching the Sessions at all. You would acquire them when needed, and close them immediately after use, that is after you've commit()ed your transaction (reliably, via a finally block or try-with-resources construct).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top