Java 如何避免陈旧的MySQL/Hibernate连接(MySQLNonTransientConnectionException)

Java 如何避免陈旧的MySQL/Hibernate连接(MySQLNonTransientConnectionException),java,mysql,hibernate,Java,Mysql,Hibernate,我有一个使用Hibernate和MySQL的JavaWebApp。如果站点几天没有使用,MySQL连接就会失效,我会遇到以下异常: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state. 根据使用原始JDBC的经验,可以将连接配置为尝试从错误或陈旧的连接中恢复

我有一个使用Hibernate和MySQL的JavaWebApp。如果站点几天没有使用,MySQL连接就会失效,我会遇到以下异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
根据使用原始JDBC的经验,可以将连接配置为尝试从错误或陈旧的连接中恢复,但我不知道如何使用Hibernate实现这一点。我并没有在任何地方显式地调用close()(但我敢打赌Hibernate在它的内心深处是这样做的)


有人知道我应该做什么吗?

您使用的是什么连接池


问题不是使用内置池,而是使用应用程序服务器数据源或类似或的东西。

我遇到了这个问题。使用连接池(c3p0)使它消失了。一般来说,使用一些连接池也是一个好主意。

谢谢您的建议。为了子孙后代,我将hibernate.cfg.xml从以下内容更改为:

<property name="connection.url">jdbc:mysql://localhost/FooDB</property>
<property name="connection.username">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.password">secret</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="connection.datasource">java:/comp/env/jdbc/FooDB</property> 
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
jdbc:mysql://localhost/FooDB
根
com.mysql.jdbc.Driver
org.hibernate.dialogue.mysqldialogue
秘密
org.hibernate.transaction.jdbc事务工厂
。。。对下列事项:

<property name="connection.url">jdbc:mysql://localhost/FooDB</property>
<property name="connection.username">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.password">secret</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="connection.datasource">java:/comp/env/jdbc/FooDB</property> 
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
java:/comp/env/jdbc/FooDB
org.hibernate.dialogue.mysqldialogue
这还需要在我的web应用程序的context.xml中添加一个标准的“context”条目:

<Resource name="jdbc/FooDB"
          auth="Container"
          type="javax.sql.DataSource"
          maxActive="100"
          maxIdle="30"
          maxWait="10000"
          username="root"
          password="secret"
          driverClassName="com.mysql.jdbc.Driver"
          url="jdbc:mysql://localhost:3306/ss?autoReconnect=true" />



我们遇到了类似的问题,hibernate mysql连接超时。 因此,我们尝试了C3P0,配置如下:

<property name=c3p0.acquire_increment>1</property>
<property name=c3p0.idle_test_period>3600</property> 
<property name=c3p0.max_statements>0</property> 
<property name=c3p0.min_size>1</property> 
<property name=c3p0.timeout>3605</property> 
<property name=hibernate.c3p0.preferredTestQuery>select 1;</property>
1
3600
0
1.
3605
选择1;
休眠连接池大小设置为1

这使得超时问题消失了。但我们开始面临另一个问题。漫长的等待。 我们有一个服务(在jboss上运行的servlet),它每秒接收大约5-6个请求。每个请求都需要通过hibernate连接到mysql。我们的大多数请求都会进行选择,每5-6次请求都会进行插入/更新。通常,对于select,我们的请求服务时间为2-3ms,对于insert/update,我们的请求服务时间为40-50ms。但是,在使用上述C3P0配置之后,我们发现在更新之后完成每个请求几乎需要4-5分钟!从我们的日志来看,随机选择的请求似乎会被卡住,只有在收到并提供更新请求后才能完成

如果我们删除C3P0配置,上述问题就会消失。有人能指出我们做错了什么吗

以下是完整的hibernate配置供参考:

<?xml version="1.0" encoding="utf-8" ?>
<!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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://xxx.xxx.xxx</property>
        <property name="connection.username">xxx</property>
        <property name="connection.password">xxx</property>
        <property name="connection.pool_size">1</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.cache.use_query_cache">false</property>
        <property name="hibernate.cache.use_second_level_cache">false</property>
        <property name="show_sql">true</property>
        <!-- Transaction isolation 2 = READ_COMMITTED -->
        <property name="connection.isolation">2</property>
        <property name="connection.autocommit">true</property>
        <!-- configuration pool via c3p0-->
        <property name="c3p0.acquire_increment">1</property>
        <property name="c3p0.idle_test_period">3600</property> <!-- seconds -->
        <property name="c3p0.max_size">1</property>
        <property name="c3p0.max_statements">0</property>
        <property name="c3p0.min_size">1</property>
        <property name="c3p0.timeout">3605</property> <!-- seconds -->
        <property name="hibernate.c3p0.preferredTestQuery">select 1;</property>
    </session-factory>
</hibernate-configuration>

com.mysql.jdbc.Driver
jdbc:mysql://xxx.xxx.xxx
xxx
xxx
1.
org.hibernate.dialogue.mysqldialogue
线
假的
假的
真的
2.
真的
1.
3600
1.
0
1.
3605
选择1;
1
120
100
0
10
180

覆盖配置文件中的这些设置。这将对您有所帮助。

您是否尝试对连接使用
isValid
来测试连接是否有效,如果无效,则重新连接。我认为这应该可以解决问题,而不必更改服务器设置