数据持久层:Hibernate 3.1
连接池:proxool 0.8.3症状描述: 正常操作没有问题,如果过上一段时间不操作,比较机器闲置半小时(TOMCAT容器正常工作)左右,当你再次操作的时候,报500错误,说connection.close()方法已经被执行。错误详情如下:
ERROR[http-8080-Processor23](StandardWrapperValve.java:253)-Servlet.service() for servlet action threw exception
com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:981)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:957)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.ConnectionImpl.getMutex
.......
--------------------------------------------------------
下面是几个主要的配置文件,贴出来:
hibernate.cfg.xml<?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="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="show_sql">true</property> <!-- proxool connection pool config -->
<property name="proxool.pool_alias">dbpool</property>
<property name="proxool.xml">proxool_conf.xml</property>
<property name="connection.provider_class">org.hibernate.connection.ProxoolConnectionProvider</property>
<mapping resource="com/erp/puaite/main/TbAdmin.hbm.xml" />
<mapping resource="com/erp/puaite/main/TbProduct.hbm.xml" />
<mapping resource="com/erp/puaite/main/TbSuppliers.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbMonthlyBuylistSummaryDetil.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbMonthlyBuylistSummary.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbNewaddPlannedBuylistDetil.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbNewaddPlannedBuylist.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbProducingPlannedBuylistDetil.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbProducingPlannedBuylist.hbm.xml" />
<mapping resource="com/erp/puaite/main/TbReceiveGoods.hbm.xml" />
<mapping resource="com/erp/puaite/main/TbSendmoneyList.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbStockMonthlyReportDetil.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbStockMonthlyReport.hbm.xml" />
<mapping
resource="com/erp/puaite/main/TbSupplierGivingPrice.hbm.xml" /></session-factory></hibernate-configuration>
proxool_conf.xml<?xml version="1.0" encoding="UTF-8"?><something-else-entirely> <proxool>
<alias>dbpool</alias>
<driver-url>jdbc:mysql://localhost:3306/db_puaite?useUnicode=true&amp;characterEncoding=utf-8</driver-url>
<driver-class>org.gjt.mm.mysql.Driver</driver-class>
<driver-properties>
<property name="user" value="root" />
<property name="password" value="186899" />
</driver-properties>
<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<maximum-active-time>60000</maximum-active-time>
<maximum-new-connections>100</maximum-new-connections>
<prototype-count>5</prototype-count>

<maximum-connection-count>50</maximum-connection-count>
<minimum-connection-count>10</minimum-connection-count>
</proxool></something-else-entirely>web.xml<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>
      <param-value>3</param-value>
    </init-param>
    <init-param>
      <param-name>detail</param-name>
      <param-value>3</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>/html/*</url-pattern>
  </servlet-mapping>
  
  <filter>
   <filter-name>myfilter</filter-name>
   <filter-class>com.erp.puaite.filter.MyFilter</filter-class>
  </filter>
  <filter-mapping>
   <filter-name>myfilter</filter-name>
   <url-pattern>/html/admin/*</url-pattern>
  </filter-mapping>
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
获取Session的工具类package sessionFactory;import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class HibernateSessionFactory {    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    private  static Configuration configuration = new Configuration();
    private static org.hibernate.SessionFactory sessionFactory;
    private static String configFile = CONFIG_FILE_LOCATION; static {
     try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
    }
    private HibernateSessionFactory() {
    }


    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}        return session;
    } /**
     *  Rebuild hibernate session factory
     *
     */
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
} /**
     *  Close the single hibernate session instance.
     *
     *  @throws HibernateException
     */
    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);        if (session != null) {
            session.close();
        }
    } /**
     *  return session factory
     *
     */
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
} /**
     *  return session factory
     *
     * session factory will be rebuilded in the next call
     */
public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
} /**
     *  return hibernate configuration
     *
     */
public static Configuration getConfiguration() {
return configuration;
}}备注:我发现闲置一段时间之后,proxool在控制台自动打印出以下几句话:
WARN[HouseKeeper](HouseKeeper.java:142)-#0002 was active for 152813 milliseconds and has been removed automaticaly. The Thread responsible was named 'http-8080-Processor24'.
WARN[HouseKeeper](HouseKeeper.java:142)-#0014 was active for 85469 milliseconds and has been removed automaticaly. The Thread responsible was named 'http-8080-Processor23'.辛苦大家啦!

解决方案 »

  1.   

    proxool配置文件中的参数maximum-active-time
    <maximum-active-time>60000</maximum-active-time>其含义是一个线程持有一个连接的最长时间,而不管这个连接是否处于 active 状态, 并且如果线程的持有时间超过这个时间的之后会自动清除掉这个连接. 60000=5分钟,一般是不够的,请加大这个值到最大的可能空闲时间之上。
      

  2.   

    proxool配置文件中的参数maximum-active-time默认时间是5分钟,60000=1分钟吧!应该是以毫秒为最小单位的
      

  3.   

    =======================
    proxool配置文件中的参数maximum-active-time
    <maximum-active-time>60000 </maximum-active-time>其含义是一个线程持有一个连接的最长时间,而不管这个连接是否处于 active 状态, 并且如果线程的持有时间超过这个时间的之后会自动清除掉这个连接.60000=5分钟,一般是不够的,请加大这个值到最大的可能空闲时间之上。
    ===================================
    2楼同志我有个问题,如果我的空闲时间还是超过了maximum-active-time所规定的时间,那么我就只能重起web服务了吗?
      

  4.   


    “如果我的空闲时间还是超过了maximum-active-time所规定的时间……”  如果空闲时间超过了规定时间,当前线程好像被杀掉了,在访问就报找不到connection的错误,但是我把当前的浏览器关掉,再打开浏览器输上地址访问,又能访问了,如果又超时了,那么再次被杀掉,还得重开浏览器,这样周而复始。   如果连接池能够自动重新获取数据库连接就好了,避免出现烦人的500错误。
      

  5.   

    重大失误:忘记给shagoo师傅加分啦,现在也不能回滚了。我只能以语言的方式向shagoo师傅表示由衷的谢意。