1

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

我收到“事务仍处于活动状态时无法关闭连接”;它似乎出现在为休眠配置事物的过程中,但我在数据库中创建的记录无论如何都会写在那里。我已经尝试过非“40”驱动程序,我已经将用户名和密码作为 URL 参数而不是在休眠配置中单独输入,我无法弄清楚可能正在运行的其他事务。我在循环中对 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 基类曾经在这里;它现在在下面的编辑中,因为我替换了它:

休眠配置文件:

    <!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 的回答之后更新

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

2 回答 2

2

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

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

编写一个适当的 HibernateUtil 类(例如在这里);或执行以下操作:

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 行阅读此处的注释,然后尝试将 property hibernate.temp.use_jdbc_metadata_defaults属性设置为 false。

该属性已从休眠 4.x 中删除

于 2013-02-19T13:42:00.753 回答
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

于 2013-02-19T04:23:11.603 回答