Reputation: 13133
I am using Hibernate (trying to learn) and Derby; I create and inspect the database using Squirrel and an SQL script, and am writing 3 records to it in my program.
I am getting "Cannot close a connection while a transaction is still active"; it seems to appear during the configuration of things for hibernate, but the records I'm creating in the database get written there anyway. I've tried the non-"40" driver, I've put username and password in as URL parameters instead of on their own in the hibernate configuration, I cannot figure out what other transaction might be running. I've put a breakpoint at the call to create() in the loop, and by the time it is hit, the error has already appeared in the console, so it isn't anything about the records I'm writing out. Anyone have other ideas here?
Here's the main program code:
package samplerc;
import sample.CreateUser;
public class CreateRecords
{
public static void main(String[] args)
{
try
{
String[][] userList =
{ { "rc", "1" },
{ "pbh", "2" },
{ "jbc", "3" }
};
CreateUser userCreator = new CreateUser();
userCreator.addUserList(userList);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
and here's CreateUser:
package sample;
import org.hibernate.HibernateException;
import sample.dao.DAO;
import sample.entity.User;
public class CreateUser extends DAO
{
public void addUserList(String[][] userList)
throws Exception
{
try
{
for (int i=0; i<userList.length; i++)
{
create(userList[i][0], userList[i][1]);
System.out.println("Created user");
DAO.close();
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public User create(String username, String password) throws Exception
{
try
{
begin();
User user = new User(username, password);
getSession().save(user);
commit();
return user;
}
catch (HibernateException e)
{
throw new Exception("Could not create user " + username, e);
}
}
}
the DAO base class used to be here; it is now below in an edit because I replaced it:
the hibernate config file:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url"> jdbc:derby://localhost:1527/C:/Users/rcook/workspaceGalileoLaptop/BHChap3/BegHibernateDB</property>
<property name="hibernate.connection.driver_class"> org.apache.derby.jdbc.ClientDriver40 </property>
<property name="hibernate.connection.username">admin</property>
<property name="hibernate.connection.password">admin</property>
<property name="hibernate.dialect"> org.hibernate.dialect.DerbyDialect </property>
<property name="hibernate.connection.pool_size">0</property>
<property name="hibernate.show_sql">false</property>
<!-- "Import" the mapping resources here -->
<mapping class="sample.entity.Message"/>
<mapping class="sample.entity.Advert"/>
<mapping class="sample.entity.Category"/>
<mapping class="sample.entity.User"/>
</session-factory>
</hibernate-configuration>
The log file used to be here; due to posting restrictions, I've removed it since I've got another log in the edit below.
-- updated after Guido's answer
Guido, that was such an excellent idea I was certain it was right. Unfortunately the change I made doesn't seem to fix it. Here's the new DAO class, with your suggested change:
package sample.dao;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class DAO
{
private static final Logger log = Logger.getAnonymousLogger();
private static SessionFactory sessionFactory = null;
private static final ThreadLocal threadLocalSession = new ThreadLocal();
protected DAO()
{
}
private static synchronized SessionFactory getSessionFactory()
{
if (sessionFactory == null)
{
sessionFactory = new Configuration().configure().buildSessionFactory();
}
return sessionFactory;
}
public static Session getSession()
{
String threadName = Thread.currentThread().getName();
System.out.println(String.format("getting session, thread = '%s'", threadName));
Session localSession = (Session) DAO.threadLocalSession.get();
if (localSession == null)
{
try
{
localSession = getSessionFactory().openSession();
DAO.threadLocalSession.set(localSession);
}
catch (HibernateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return localSession;
}
protected void begin()
{
try
{
getSession().beginTransaction();
}
catch (HibernateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void commit()
{
try
{
getSession().getTransaction().commit();
}
catch (HibernateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void rollback()
{
try
{
getSession().getTransaction().rollback();
}
catch (HibernateException e)
{
log.log(Level.WARNING, "Cannot rollback", e);
}
try
{
getSession().close();
}
catch (HibernateException e)
{
log.log(Level.WARNING, "Cannot close", e);
}
DAO.threadLocalSession.set(null);
}
public static void close()
{
getSession().close();
// try { Thread.sleep(5000); } catch (InterruptedException ie) {}
DAO.threadLocalSession.set(null);
}
}
And here's the new log file. I stuck in a trace statement and find it's output interesting vis-a-vis the rest of the output. ANY other ideas you (or anyone else) have would be welcome.
Starting...
getting session, thread = 'main'
Feb 19, 2013 10:25:21 AM org.hibernate.annotations.common.Version <clinit>
INFO: Hibernate Commons Annotations 3.2.0.Final
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.6.10.Final
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: Bytecode provider name : javassist
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Feb 19, 2013 10:25:21 AM org.hibernate.util.DTDEntityResolver resolveEntity
WARNING: recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.AnnotationBinder bindClass
INFO: Binding entity from annotated class: sample.entity.Message
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.annotations.EntityBinder bindTable
INFO: Bind entity sample.entity.Message on table Message
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.AnnotationBinder bindClass
INFO: Binding entity from annotated class: sample.entity.Advert
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.annotations.EntityBinder bindTable
INFO: Bind entity sample.entity.Advert on table Advert
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.AnnotationBinder bindClass
INFO: Binding entity from annotated class: sample.entity.Category
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.annotations.EntityBinder bindTable
INFO: Bind entity sample.entity.Category on table Category
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.AnnotationBinder bindClass
INFO: Binding entity from annotated class: sample.entity.User
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.annotations.EntityBinder bindTable
INFO: Bind entity sample.entity.User on table AdUser
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.Configuration applyHibernateValidatorLegacyConstraintsOnDDL
INFO: Hibernate Validator not found: ignoring
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.search.HibernateSearchEventListenerRegister enableHibernateSearch
INFO: Unable to find org.hibernate.search.event.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled.
Feb 19, 2013 10:25:21 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
Feb 19, 2013 10:25:21 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 0
Feb 19, 2013 10:25:21 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: false
Feb 19, 2013 10:25:21 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: org.apache.derby.jdbc.ClientDriver40 at URL: jdbc:derby://localhost:1527/BegHibernateDB
Feb 19, 2013 10:25:21 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=admin, password=****}
Feb 19, 2013 10:25:21 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.DerbyDialect
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Database ->
name : Apache Derby
version : 10.8.1.2 - (1095077)
major : 10
minor : 8
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Driver ->
name : Apache Derby Network Client JDBC Driver
version : 10.8.1.2 - (1095077)
major : 10
minor : 8
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
WARNING: Could not obtain connection to query metadata
java.sql.SQLException: Cannot close a connection while a transaction is still active.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.Connection.closeResourcesX(Unknown Source)
at org.apache.derby.client.am.Connection.closeX(Unknown Source)
at org.apache.derby.client.net.NetConnection.closeX(Unknown Source)
at org.apache.derby.client.am.Connection.close(Unknown Source)
at org.apache.derby.client.net.NetConnection.close(Unknown Source)
at org.apache.derby.client.net.NetConnection40.close(Unknown Source)
at org.hibernate.connection.DriverManagerConnectionProvider.closeConnection(DriverManagerConnectionProvider.java:160)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:143)
at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2863)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2859)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1870)
at sample.dao.DAO.getSessionFactory(DAO.java:25)
at sample.dao.DAO.getSession(DAO.java:39)
at sample.dao.DAO.begin(DAO.java:55)
at sample.CreateUser.create(CreateUser.java:77)
at sample.CreateUser.addUserList(CreateUser.java:61)
at samplerc.CreateRecords.main(CreateRecords.java:19)
Caused by: org.apache.derby.client.am.SqlException: Cannot close a connection while a transaction is still active.
at org.apache.derby.client.am.Connection.checkForTransactionInProgress(Unknown Source)
... 17 more
Feb 19, 2013 10:25:21 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.DerbyDialect
Feb 19, 2013 10:25:21 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
Feb 19, 2013 10:25:21 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Connection release mode: auto
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL inserts for batching: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Feb 19, 2013 10:25:21 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JPA-QL strict compliance: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory createRegionFactory
INFO: Cache region factory : org.hibernate.cache.impl.NoCachingRegionFactory
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Named query checking : enabled
Feb 19, 2013 10:25:21 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Check Nullability in Core (should be disabled when Bean Validation is on): enabled
Feb 19, 2013 10:25:22 AM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [characters_clob] overrides previous : org.hibernate.type.PrimitiveCharacterArrayClobType@494eaec9
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [materialized_clob] overrides previous : org.hibernate.type.MaterializedClobType@4cb533b8
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [wrapper_materialized_blob] overrides previous : org.hibernate.type.WrappedMaterializedBlobType@c569c60
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [materialized_blob] overrides previous : org.hibernate.type.MaterializedBlobType@a3468f4
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [blob] overrides previous : org.hibernate.type.BlobType@76d67067
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [java.sql.Blob] overrides previous : org.hibernate.type.BlobType@76d67067
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [clob] overrides previous : org.hibernate.type.ClobType@786db724
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [java.sql.Clob] overrides previous : org.hibernate.type.ClobType@786db724
Feb 19, 2013 10:25:22 AM org.hibernate.type.BasicTypeRegistry register
INFO: Type registration [wrapper_characters_clob] overrides previous : org.hibernate.type.CharacterArrayClobType@11c7865b
Feb 19, 2013 10:25:22 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
getting session, thread = 'main'
getting session, thread = 'main'
Created user
getting session, thread = 'main'
getting session, thread = 'main'
getting session, thread = 'main'
getting session, thread = 'main'
Created user
getting session, thread = 'main'
getting session, thread = 'main'
getting session, thread = 'main'
getting session, thread = 'main'
Created user
getting session, thread = 'main'
Upvotes: 1
Views: 3235
Reputation: 19224
It is because in the initialization ( <clinit>
, not the constructor ) of each of your four mapped classes extending DAO, this is executed:
private static final SessionFactory sessionFactory =
new Configuration().configure().buildSessionFactory();
Write a proper HibernateUtil class (like in here for instance); or do something like:
private static final SessionFactory sessionFactory;
private static synchronized SessionFactory getSessionFactory() {
if (sessionFactory == null) {
sessionFactory = new Configuration().configure().buildSessionFactory();
}
return sessionFactory;
}
then refer to sessionFactory only through getSessionFactory().
EDIT: have a look at this: https://forum.hibernate.org/viewtopic.php?f=6&t=953499
It is exactly your problem, check the schema of your database and that database is actually in expected location.
EDIT 2: read the comment here at line 101, then try to set the property
hibernate.temp.use_jdbc_metadata_defaults
property to false.
That property has been removed from hibernate 4.x
Upvotes: 2
Reputation: 81
I looked in the current Hibernate source at the point where your code path (cf your stack trace) tries to close the connection.
Although the source I looked at [1], doesn't quite match your stack trace, I believe Hibernate has just queried Derby for database metadata as part of its setting up. Even a read-only query sets up a transaction in Derby.
If Hibernate runs this query with JDBC autocommit off, and neglected to commit (or rollback) the transaction before attempting to close the connection, you would see this error. I suggest contacting Hibernate folks about this. Maybe their Derby dialect needs some tuning.
Thanks,
Dag
Upvotes: 1