我正在使用Hibernate 3和mysql sever 5.5 for myweb application with spring 3.0
由于太多连接,我得到例外......
我创建会话的java文件如下:
public class DBConnection {
static{
}
public Session getSession(){
Session session = null;
SessionFactory sessionFactory= null;
sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
return session;
}
}
我在需要会话
的地方调用此方法as
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>
答案 0 :(得分:23)
这是因为您正在使用在构建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();
}
}
答案 1 :(得分:2)
每次需要SessionFactory
并且不关闭它们时,您都会创建新的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();
}
}
答案 2 :(得分:0)
我用过
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
我没有改变
mysql> show variables like "innodb_open_files";
在执行程序期间,您可以使用
mysql> show processlist;
找出打开的连接数。我想睡眠状态下的所有进程都可以在下一个清理周期中删除(但这只是我的猜测)。
要模拟超过1000个用户,在您的Web项目中执行一些URL,您可以使用jmeter等软件并将线程数(用户数)设置为1000.使用更多用户还取决于计算机中的可用RAM。我能够以1秒的间隔模拟超过3000个连接发送请求。 roseindia
列出了关于如何执行此操作的完整且充分的教程现在我的查询。我还没有在任何地方关闭会议。我想@Transaction是为此目的而创建的(mysql证明了这一点,因为一旦限制到达,所有这些连接都会被清除)。由于分离对象的合并问题,我不得不使用OpenSessionInViewFilter。 OpenSessionInViewFilter(可以是OpenSessionInViewInterceptor)打开会话一段时间以便合并发生,这可能是因为很多连接在mysql中保持打开的原因(不清楚)。由于它适用于这么多用户,它似乎是一个很好的解决方案,但有一个更好的解决方案,使其在默认的最大连接大小的mysql下工作。即151个连接。
答案 3 :(得分:0)
我在使用Hibernate mysql时遇到了同样的问题 以下两件事有助于解决我的连接问题
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>
在
下答案 4 :(得分:-2)
JAVA ISSUE
请检查此答案:https://stackoverflow.com/a/10785770/598424
MYSQL ISSUE
您需要登录为超级用户。然后执行此代码:
SET GLOBAL MAX_CONNECTIONS = 200;
然而,这只是在MYSQL服务器重新启动之前发生的。如果您想要永久更改它,您可以在MYSQLD部分下添加以下内容。
MAX_CONNECTIONS = 500
OR
如果您在数据库服务器上有太多的过程,那么您可以达到限制,并且不允许任何新的操作开始。
要查看是否是这种情况,请通过键入以下内容从MySQL监视器提示中查看您的进程:
show processlist;
然后你会看到挥之不去的过程。每个都有一个ID,您可以通过键入以下命令在MySQL监视器中按进程ID终止它们:
kill 2309344;