使用Derby进行Hibernate:在事务仍处于活动状态时无法关闭连接

时间:2013-02-19 03:37:48

标签: java hibernate derby

我正在使用Hibernate(试图学习)和Derby;我使用Squirrel和SQL脚本创建和检查数据库,并在我的程序中写入3条记录。

我收到“无法在交易仍处于活动状态时关闭连接”;它似乎出现在hibernate的配置过程中,但是我在数据库中创建的记录仍然会写在那里。我已经尝试了非“40”驱动程序,我已经将用户名和密码作为URL参数而不是自己在hibernate配置中,我无法弄清楚其他事务可能正在运行。我在循环中调用create()时设置了一个断点,当它被命中时,错误已经出现在控制台中,所以它与我正在写出的记录没有关系。任何人都有其他想法吗?

这是主程序代码:

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

  }

}

这里是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);
    }
  }
}

DAO基类曾经在这里;它现在在编辑中,因为我替换了它:

hibernate配置文件:

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

以前的日志文件;由于发布限制,我删除了它,因为我在下面的编辑中有另一个日志。

- 在Guido的回答后更新

圭多,这是一个非常好的主意,我确信这是对的。不幸的是,我所做的改变似乎没有解决它。这是新的DAO类,包含您建议的更改:

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

这是新的日志文件。我陷入了一个跟踪声明,发现它的输出与输出的其余部分相比很有趣。您(或其他任何人)拥有的任何其他想法都将受到欢迎。

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'

2 个答案:

答案 0 :(得分:1)

我查看当前的Hibernate源代码路径(参见堆栈跟踪)尝试关闭连接。

虽然我查看了[1]的源代码,但与您的堆栈跟踪不完全匹配,我相信Hibernate刚刚查询了Derby的数据库元数据作为其设置的一部分。即使是只读查询也会在Derby中设置事务。

如果Hibernate在JDBC自动提交关闭的情况下运行此查询,并且在尝试关闭连接之前忽略提交(或回滚)事务,则会看到此错误。我建议联系Hibernate人员。也许他们的德比方言需要一些调整。

谢谢,
达格

[1] https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java

答案 1 :(得分:1)

这是因为在扩展DAO的四个映射类中的每一个的初始化(<clinit>,而不是构造函数)中,都会执行:

private static final SessionFactory sessionFactory = 
   new Configuration().configure().buildSessionFactory();

编写一个合适的HibernateUtil类(例如在here中);或做类似的事情:

private static final SessionFactory sessionFactory;

private static synchronized SessionFactory getSessionFactory() {
     if (sessionFactory == null) {
          sessionFactory = new Configuration().configure().buildSessionFactory();
     }
     return sessionFactory;
}

然后仅通过getSessionFactory()引用sessionFactory。

编辑:看看这个:https://forum.hibernate.org/viewtopic.php?f=6&t=953499

这正是您的问题,请检查数据库和该数据库的架构 实际上是在预期的位置。

编辑2:阅读第101行的评论here,然后尝试设置属性 hibernate.temp.use_jdbc_metadata_defaults属性为false。

该属性已从hibernate 4.x中删除