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

时间:2009-04-06 15:16:21

标签: java mysql hibernate

我有一个使用Hibernate和MySQL的Java webapp。如果该网站未使用几天,MySQL连接将失效,并且我遇到以下异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.

根据使用原始JDBC的经验,可以配置连接以尝试从错误或过时连接中恢复,但我不知道如何使用Hibernate执行此操作。我并没有明确地在任何地方调用close()(但是我认为Hibernate会在内心深处进行调整)。

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

5 个答案:

答案 0 :(得分:4)

您使用的是什么连接池?

Hibernate suggestion不使用内置池,而是使用应用服务器数据源或类似Commons DBCPC3PO的内容。

答案 1 :(得分:3)

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

答案 2 :(得分:2)

感谢您的建议。为了后人的缘故,我改变了以下的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>

这还需要在我的网络应用的context.xml中添加标准的“上下文”条目:

<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" />

答案 3 :(得分:1)

我们有一个类似的问题,即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>

Hibernate connection_pool size设置为1。

这使得超时问题消失了。但我们开始面临另一个问题。漫长的等待。 我们有一个服务(在jboss上运行的servlet),每秒接收5-6个请求。每个请求都需要通过hibernate连接到mysql。我们的大多数请求都会选择,每隔5到6次请求插入/更新一次。通常,对于我们来说,请求服务时间为2-3ms,插入/更新为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>

答案 4 :(得分:1)

<property name="c3p0.acquire_increment">1</property> 
<property name="c3p0.idle_test_period">120</property> <!-- seconds --> 
<property name="c3p0.max_size">100</property> 
<property name="c3p0.max_statements">0</property> 
<property name="c3p0.min_size">10</property> 
<property name="c3p0.timeout">180</property> <!-- seconds --> 

覆盖配置文件中的这些设置。它会对你有所帮助。