I have a problem using c3p0. In the following code snippet (simplified from what I am really doing) I create a statement that will not be closed when a transaction is committed (the parameter ResultSet.HOLD_CURSORS_OVER_COMMIT). In the code, I iterate over the result set and periodically commit the transaction and start a new one. I do this because of a memory leak in the database driver. In reality the memory leak only becomes a problem around 25,000 records, which is when I commit in the production code.
This code works fine as long as I do not use c3p0. But when I do use c3p0, executing the results.next() statement after the first commitTransaction() inside the while loop, I receive a SqlException stating that the result set has been closed.
Code:
Statement statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
statement.execute(query);
ResultSet results = statement.getResultSet();
int normRecCount = 0;
hibUtil.beginTransaction();
while (results.next() {
// create a mapped object called normRec from the result set row;
hibUtil.saveObject(normRec);
normRecCount++;
if (normRecCount % 100 == 0) {
hibUtil.commitTransaction();
hibUtil.beginTransaction();
}
}
hibUtil.commitTransaction();
hibUtil in the code is an implenmentation of the HibernateUtility class pretty much like the one in the CaveatEmptor example application. It uses a threadLocal variable to hold the hibernate Session. Using this paradigm only one transaction per thread is supported.
My questions are:
- Does anyone know of a way to get c3p0 to correctly recognize the HOLD_CURSORS_OVER_COMMIT parameter?
- Might another connection pool work correctly? I don't want to spend a lot of time on other connection pools if they will all have this same issue.
- Is there another way to construct the code to avoid this problem and still use c3p0?
(My thoughts were to manage transactions explicitly, i.e. not use HibernateUtility, so I could use different transactions for the query and update statements; or to run the update, that is the saveObject() code, in a separate thread so that even using HibernateUtil it will have a different Session.)
I am using hibernate 3.2, DB2 version 8.2, java 1.5. Here are my c3p0 statements in hibernate.cfg.xml:
Code:
<property name="hibernate.c3p0.min_size">50</property>
<property name="hibernate.c3p0.max_size">200</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">5000</property>