【问题标题】:Hibernate's session.connection Error: "Too many users"Hibernate 的 session.connection 错误:“用户太多”
【发布时间】:2011-06-23 20:26:09
【问题描述】:

我正在使用 Hibernate 开发一个 Java Web 应用程序,但其中一部分我想使用 JDBC,因为我正在动态创建查找表。

使用我的网络应用几分钟后,我收到此错误:

com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: 数据源拒绝建立 连接,来自服务器的消息:“太 许多连接”

我知道不推荐使用 session.connection(),但我只想获取底层的 JDBC 连接。我尝试使用 session.doWork() 但错误仍然像以前一样发生。

代码如下:

领域层:

/**
 * Goes through the list of lookupTableAbstractions and persists each one
 * @param lookupData
 */
public void updateLookupValues( List<LookupTableAbstraction> lookupData )
{
    lookupTablesData.dropAllLookupTables(lookupData);

    lookupTablesData.createLookupTables(lookupData);

    for (LookupTableAbstraction lookupTable : lookupData)
        lookupTablesData.persistLookupTableValues(lookupTable);
}

数据层:

public LookupTableAbstraction getLookupTable( String tableName )
{
    LookupTableAbstraction lookupTable = new LookupTableAbstraction();

    Session session = getSessionFactory().openSession();

    String sqlQuery = "select value from " + tableName;

    List<String> lookupTableValues = session.createSQLQuery(sqlQuery).list();

    session.close(); 

    lookupTable.setTableName(tableName);
    for (String value : lookupTableValues)
        lookupTable.addValue(value);

    return lookupTable;
}

/**
 * Persists the passed in lookup table.
 * The lookup table that is used is determine by
 * the tableName field of the passed in lookupTable
 * @param lookupTable
 */
public void persistLookupTableValues( LookupTableAbstraction lookupTable )
{
    Session session = getSessionFactory().openSession();
    Transaction tx = session.beginTransaction();
    Connection connection = null;
    try
    {
        connection = getJDBCConnectionFromHibernate(session);

        Statement stmt = connection.createStatement();

        String tableName = lookupTable.getTableName();
        for (String value : lookupTable.getValues() ) 
        {
            String sql = " insert into " + tableName + 
                         " (value) " +
                         " values " +
                         "('" + value + "')";

            System.out.println(sql);

            stmt.executeUpdate(sql);
        }
        stmt.close();
    }
    catch( Exception e )
    {
        System.out.println("Exception(persistLookupTableValues): " + e.getMessage());
        e.printStackTrace();
    }
    finally
    {

        try {
            tx.commit();
            connection.close();
            session.close();
        } catch (SQLException e) {
            System.out.println("Exception(persistLookupTableValues): " + e.getMessage());
            e.printStackTrace();
        }
    }
}

/**
 * Drop's all lookup tables.
 * It drops each table based off the lookupTableAbstractions in the passed in list
 * @param lookupData
 */
public void dropAllLookupTables( List<LookupTableAbstraction> lookupData )
{
    Session session = getSessionFactory().openSession();
    Transaction tx = session.beginTransaction();

    Connection connection = null;
    try
    {
        connection = getJDBCConnectionFromHibernate(session);

        Statement stmt = null;
        for (LookupTableAbstraction lookupTableAbstraction : lookupData) {
            stmt = connection.createStatement();
            stmt.executeUpdate("drop table " + lookupTableAbstraction.getTableName());
        }

        stmt.close();
    }
    catch( Exception e )
    {
        System.out.println("Exception(dropAllLookupTables): " + e.getMessage());
        e.printStackTrace();
    }
    finally
    {
        try {
            tx.commit();
            connection.close();
            session.close();
        } catch (SQLException e) {
            System.out.println("Exception(dropAllLookupTables): " + e.getMessage());
            e.printStackTrace();
        }
    }
}

/**
 * Creates all lookup tables, one for each lookupTableAbstraction
 * in the passed in list
 * @param lookupData
 */
public void createLookupTables( List<LookupTableAbstraction> lookupData )
{
    Session session = getSessionFactory().openSession();
    Transaction tx = session.beginTransaction();

    Connection connection = null;
    try
    {
        connection = getJDBCConnectionFromHibernate(session);

        Statement stmt = null;
        for (LookupTableAbstraction lookupTableAbstraction : lookupData) {
            stmt = connection.createStatement();
            stmt.executeUpdate("create table " + lookupTableAbstraction.getTableName() + 
                               " ( ID  int(11) auto_increment, " +
                               "  value text, " +
                               "  primary key (ID) )");
        }

        stmt.close();
    }
    catch( Exception e )
    {
        System.out.println("Exception(createLookupTables): " + e.getMessage());
        e.printStackTrace();
    }
    finally
    {
        try {
            tx.commit();
            connection.close();
            session.close();
        } catch (SQLException e) {
            System.out.println("Exception(createLookupTables): " + e.getMessage());
            e.printStackTrace();
        }
    }
}

protected Connection getJDBCConnectionFromHibernate( Session session )
{
    return session.connection();
}

感谢您的任何建议

【问题讨论】:

  • 您肯定会以某种方式泄漏连接。要验证这一点,您可以监控应用程序正在使用的连接数吗?如果启用了统计信息,您可以从会话工厂获取此值。 session.getSessionFactory().getStatistics().getConnectionCount().
  • 您能看到您在代码中登录的任何异常吗?
  • 嗨 Pace,我启用了统计功能,并且在我使用该应用程序时,它始终保持在 1 个连接。嗨,axtavt,唯一抛出的异常是当我收到“用户过多”异常时。
  • 嗯,恐怕我不知道是什么导致了这个问题。您知道您是否使用池连接提供程序?连接池可能只是设置为大于 MySQL 允许的值(默认情况下我认为这是 100),并且这种错误配置直到现在才暴露出来。调试问题的另一种方法是下载 Hibernate 源代码并找出调用 Connection.close() 时到底发生了什么(Hibernate 返回的连接实际上是代理,而不是真正的底层连接)

标签: mysql hibernate jdbc


【解决方案1】:

我解决了这个问题。

我一遍又一遍地创建会话工厂。

所以,我这样做了:

protected static SessionFactory sessionFactory = null;

static 
{
    sessionFactory = new Configuration().configure().buildSessionFactory();
}

/**
 * Returns a Hibernate session factory
 * @return
 */
protected static SessionFactory getSessionFactory()
{       
    return sessionFactory;
}

【讨论】:

    【解决方案2】:

    同样的问题。网上很多例子都忘记关闭会话工厂。如果你不关闭它,你会得到 mysql “too many connections” 错误。用这行代码关闭它:

    fact.close();
    

    假设你将它命名为 fact 如下:

    SessionFactory fact = new Configuration().configure().buildSessionFactory();
    

    【讨论】:

      猜你喜欢
      • 2011-04-01
      • 1970-01-01
      • 2012-03-02
      • 2012-10-09
      • 1970-01-01
      • 2012-01-17
      • 2017-10-27
      • 1970-01-01
      • 2016-04-02
      相关资源
      最近更新 更多