6

我正在将 Hibernate 3 和 mysql sever 5.5 用于带有 spring 3.0 的 myweb 应用程序

由于连接太多,我收到异常......

我在其中创建会话的 java 文件如下:

public class DBConnection {

    static{

    }

    public Session getSession(){

         Session session = null;
         SessionFactory sessionFactory= null;
         sessionFactory = new Configuration().configure().buildSessionFactory();
        session = sessionFactory.openSession();
        return session;

    }

}

我在需要会话的地方调用这个方法

作为

Session session=new DBConnection().getSession();

之后

transaction.commit();

我通过使用关闭会话

session.close();

请帮我解决问题......

我的 hibernate.cfg.xml 是:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/dbname</property>
<property name="hibernate.connection.username">root</property>

  <property name="hibernate.connection.password">lax</property>
  <property name="hibernate.connection.pool_size">100</property>
  <property name="show_sql">true</property>
  <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
  <property name="hibernate.hbm2ddl.auto">update</property>
  <property name=""></property>

  <property name="hibernate.connection.release_mode">on_close</property>

</session-factory>
</hibernate-configuration>
4

5 回答 5

26

这是因为您使用的是在构建 SessionFactory 时立即创建的连接池,但只有在打开 Session 时才会获取连接。现在,您正在关闭会话,因为连接被释放,但没有关闭并被池阻止。现在,您再次创建一个 SessionFactory,从而创建一个新池,然后获取一个会话,从而创建一个新连接等等......最终将达到允许的最大连接数。

您需要做的是使用一个连接池(使用一个 SessionFactory)并从同一个池中获取和释放连接。

public class DBConnection {

      private static SessionFactory factory;
      static {
            factory = new Configuration().configure().buildSessionFactory();
      }

      public Session getSession() {
            return factory.openSession();
      }

      public void doWork() {
           Session session = getSession();
           // do work.
           session.close();
      }

     // Call this during shutdown
     public static void close() {
          factory.close();
     }
}
于 2012-05-28T13:52:00.853 回答
5

SessionFactory每次需要 a 时都创建新的Session,不要关闭它们。

通常您只需要在应用程序启动期间创建一次会话工厂,并在关闭期间将其关闭。例如,如下所示:

public class DBConnection {
    private static SessionFactory factory;
    static {
        factory = new Configuration().configure().buildSessionFactory();
    }

    public Session getSession() {
        return factory.openSession();
    }

    // Call this during shutdown
    public static void close() {
        factory.close();
    }
}

还要看看上下文会话模式

于 2012-05-28T11:17:37.640 回答
1

我用过

Session session = SessionFactoryUtils.getSession(this.sessionFactory,
                true);

获得会话。在 DAO 层之上,带有注释的事务(@Transactional)用于添加、编辑或删除。我们的应用程序使用 shiro 进行身份验证和授权。在每个页面访问中,它至少创建 5 个连接。所以后续请求不断增加mysql连接。感谢@Venu,我发现

show variables like "max_connections";

显示可用的默认最大连接数。最初(我猜)它被设置为 151。这个数字很快就会用完,因为另一个变量“innodb_open_files”被设置为 300。凭直觉我可以说如果一个表达到 300 的最大连接它只会去清理(就像java中的垃圾收集)。

有人会想,如果我们将“max_connections”的值增加到 300,它可以解决这个错误,但正如我之前所说,“innodb_open_files”在一个表达到该限制之前不会进行清理。在我们的例子中,经常调用的用户表将达到清理发生的限制。这意味着,您无法事先知道“max_connections”的完美数字是多少。

在 mysql 配置文件“/etc/mysql/my.cnf”中,max_connections 设置为

max_connections        = 1000

我没有改变

“innodb_open_files”的值,默认为“300”

mysql> show variables like "innodb_open_files";

在执行程序期间,您可以使用

mysql> show processlist;

找出有多少连接是打开的。我猜所有处于睡眠状态的进程都可以在下一个清理周期中被删除(但这只是我的猜测)。

要模拟超过 1000 个用户,在您的 Web 项目中执行一些 url,您可以使用 jmeter 之类的软件并将线程(用户)数设置为 1000。使用更多用户还取决于您计算机中的可用 RAM。我能够模拟 3000 多个连接以 1 秒的间隔发送请求。roseindia上列出了有关如何执行此操作的良好且足够的教程

现在我的查询。我没有在任何地方关闭会话。我猜@Transaction 是为此目的而创建的(mysql 证明了这一点,因为一旦达到限制,所有这些连接都会被清除)。由于分离对象的合并问题,我不得不使用 OpenSessionInViewFilter。OpenSessionInViewFilter (可以是 OpenSessionInViewInterceptor )打开会话的时间稍长一些,以便合并发生,这可能是 mysql 中保持打开这么多连接的原因(不清楚)。由于它适用于这么多用户,这似乎是一个很好的解决方案,但是是否有更好的解决方案可以使其在 mysql 的默认最大连接大小下工作。即151个连接。

于 2012-09-05T11:06:35.783 回答
1

我在使用 Hibernate mysql conenctions 时遇到了同样的问题以下两件事帮助解决了我的连接问题

import javax.inject.Singleton;

@Singleton
public class DBConnection {
private static SessionFactory factory;
static public Session getSession() {
    if (factory == null) {
        System.out.println("--------New connection----");

        factory = new Configuration().configure("hibernate.cfg.xml")
                .addAnnotatedClass(SomeClass.class)
                .buildSessionFactory();
    }
    //System.out.println("--------old connection----");

    return factory.openSession();
}


    // Call this during shutdown
    public static void close() {
        factory.close();
    }
}

创建一个用于获取 DBConnection 的单例类

查询完成后不要忘记执行session.close()

同样在“hibernate.cfg.xml”中添加这一行

<hibernate-configuration> <session-factory> .... <property name="connection.pool_size">100</property> .... </session-factory> </hibernate-configuration>

在下面

于 2020-05-30T15:05:31.910 回答
-2

JAVA问题

请检查这个答案:https ://stackoverflow.com/a/10785770/598424

MYSQL 问题

您需要以超级用户身份登录。然后执行此代码:

SET GLOBAL MAX_CONNECTIONS = 200;

但是,这只持续到 MYSQL 服务器重新启动。如果您想永久更改它,可以在 MYSQLD 部分下添加以下内容。

MAX_CONNECTIONS = 500

或者

如果您有太多的进程在数据库服务器上徘徊,那么您可能会达到一个限制,并且不允许启动新的进程。

要查看是否是这种情况,请通过键入以下命令从 MySQL Monitor 提示符查看您的进程:

show processlist;

然后你会看到挥之不去的过程。每个都有一个 ID,您可以通过键入以下命令在 MySQL Monitor 中按进程 ID 杀死它们:

 kill 2309344;
于 2012-05-28T11:06:01.303 回答