Hibernate-mysql-c3p0 的连接丢失问题

发布于 2024-09-02 05:37:55 字数 6787 浏览 10 评论 0 原文

这是我在网上看到的一个问题。我会再次提出这个问题,因为到目前为止我还没有解决这个问题。

  I am using hibernate 3. mysql 5 and latest c3p0 jar. I am getting a broken pipe exception. Following is my hibernate.cfg file.

com.mysql.jdbc.驱动程序 org.hibernate.dialect.MySQLDialect

    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.use_sql_comments">true</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="connection.autoReconnect">true</property>
    <property name="connection.autoReconnectForPools">true</property>
    <property name="connection.is-connection-validation-required">true</property>

    <!--<property name="c3p0.min_size">5</property>
    <property name="c3p0.max_size">20</property>
    <property name="c3p0.timeout">1800</property>
    <property name="c3p0.max_statements">50</property>


   --><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider
</property>
    <property name="hibernate.c3p0.acquireRetryAttempts">30</property>
    <property name="hibernate.c3p0.acquireIncrement">5</property>
    <property name="hibernate.c3p0.automaticTestTable">C3P0TestTable</property>

    <property name="hibernate.c3p0.idleConnectionTestPeriod">36000</property>

    <property name="hibernate.c3p0.initialPoolSize">20</property>
    <property name="hibernate.c3p0.maxPoolSize">100</property>
    <property name="hibernate.c3p0.maxIdleTime">1200</property>
    <property name="hibernate.c3p0.maxStatements">50</property>
    <property name="hibernate.c3p0.minPoolSize">10</property>-->  

我的连接池运行良好。白天没问题,但是一旦我让它在晚上闲置,第二天我发现它给我带来了连接中断的错误。

public class HibernateUtil {

private static Logger log = Logger.getLogger(HibernateUtil.class);
//private static Log log = LogFactory.getLog(HibernateUtil.class);

private static Configuration configuration;
private static SessionFactory sessionFactory;

static {
    // Create the initial SessionFactory from the default configuration files
    try {

        log.debug("Initializing Hibernate");

        // Read hibernate.properties, if present
        configuration = new Configuration();
        // Use annotations: configuration = new AnnotationConfiguration();

        // Read hibernate.cfg.xml (has to be present)
        configuration.configure();

        // Build and store (either in JNDI or static variable)
        rebuildSessionFactory(configuration);

        log.debug("Hibernate initialized, call HibernateUtil.getSessionFactory()");
    } catch (Throwable ex) {
        // We have to catch Throwable, otherwise we will miss
        // NoClassDefFoundError and other subclasses of Error
        log.error("Building SessionFactory failed.", ex);
        throw new ExceptionInInitializerError(ex);
    }
}

/**
 * Returns the Hibernate configuration that was used to build the SessionFactory.
 *
 * @return Configuration
 */
public static Configuration getConfiguration() {
    return configuration;
}

/**
 * Returns the global SessionFactory either from a static variable or a JNDI lookup.
 *
 * @return SessionFactory
 */
public static SessionFactory getSessionFactory() {
    String sfName = configuration.getProperty(Environment.SESSION_FACTORY_NAME);
    System.out.println("Current s name is "+sfName);
    if ( sfName != null) {
        System.out.println("Looking up SessionFactory in JNDI");
        log.debug("Looking up SessionFactory in JNDI");
        try {
            System.out.println("Returning new sssion factory");
            return (SessionFactory) new InitialContext().lookup(sfName);
        } catch (NamingException ex) {
            throw new RuntimeException(ex);
        }
    } else if (sessionFactory == null) {
        System.out.println("calling rebuild session factory now");
        rebuildSessionFactory();
    }
    return sessionFactory;
}

/**
 * Closes the current SessionFactory and releases all resources.
 * <p>
 * The only other method that can be called on HibernateUtil
 * after this one is rebuildSessionFactory(Configuration).
 */
public static void shutdown() {
    log.debug("Shutting down Hibernate");
    // Close caches and connection pools
    getSessionFactory().close();

    // Clear static variables
    sessionFactory = null;
}


/**
 * Rebuild the SessionFactory with the static Configuration.
 * <p>
 * Note that this method should only be used with static SessionFactory
 * management, not with JNDI or any other external registry. This method also closes
 * the old static variable SessionFactory before, if it is still open.
 */
 public static void rebuildSessionFactory() {
    log.debug("Using current Configuration to rebuild SessionFactory");
    rebuildSessionFactory(configuration);
 }

/**
 * Rebuild the SessionFactory with the given Hibernate Configuration.
 * <p>
 * HibernateUtil does not configure() the given Configuration object,
 * it directly calls buildSessionFactory(). This method also closes
 * the old static variable SessionFactory before, if it is still open.
 *
 * @param cfg
 */
 public static void rebuildSessionFactory(Configuration cfg) {
    log.debug("Rebuilding the SessionFactory from given Configuration");
    if (sessionFactory != null && !sessionFactory.isClosed())
        sessionFactory.close();
    if (cfg.getProperty(Environment.SESSION_FACTORY_NAME) != null) {
        log.debug("Managing SessionFactory in JNDI");
        cfg.buildSessionFactory();
    } else {
        log.debug("Holding SessionFactory in static variable");
        sessionFactory = cfg.buildSessionFactory();
    }
    configuration = cfg;
 }

}

上面是我的会话工厂代码。而且我只有选择操作。

下面是执行我的选择查询时最常用的方法。我不明白的一件棘手的事情是在我的 findById 方法中我使用这行代码 getSession().beginTransaction();如果没有它,它会给我一个错误,说没有交易就不会发生这种情况。但我在任何地方都不会结束这笔交易。除了提交或回滚(据我所知)之外,没有其他方法可以关闭事务,这不适用于 select 语句。

public T findById(ID id, boolean lock) 抛出 HibernateException, DAOException { log.debug("findNyId 使用 ID ="+id+" 和 lock ="+lock 调用); T实体; getSession().beginTransaction();

    if (lock)
        entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
    else
        entity = (T) getSession().load(getPersistentClass(), id);

    return entity;
}

谁能建议我能做什么?我已经尝试了几乎所有通过谷歌搜索、stackoverlow 或 hibernate 论坛上可用的解决方案,但都没有效果。 (在我的情况下,增加 mysql 上的 wait_timeout 不是一个有效的选项)。

This is an issue which I have seen all across the web. I will bring it up again as till now I don't have a fix for the same.

  I am using hibernate 3. mysql 5 and latest c3p0 jar. I am getting a broken pipe exception. Following is my hibernate.cfg file.

com.mysql.jdbc.Driver

org.hibernate.dialect.MySQLDialect

    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.use_sql_comments">true</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="connection.autoReconnect">true</property>
    <property name="connection.autoReconnectForPools">true</property>
    <property name="connection.is-connection-validation-required">true</property>

    <!--<property name="c3p0.min_size">5</property>
    <property name="c3p0.max_size">20</property>
    <property name="c3p0.timeout">1800</property>
    <property name="c3p0.max_statements">50</property>


   --><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider
</property>
    <property name="hibernate.c3p0.acquireRetryAttempts">30</property>
    <property name="hibernate.c3p0.acquireIncrement">5</property>
    <property name="hibernate.c3p0.automaticTestTable">C3P0TestTable</property>

    <property name="hibernate.c3p0.idleConnectionTestPeriod">36000</property>

    <property name="hibernate.c3p0.initialPoolSize">20</property>
    <property name="hibernate.c3p0.maxPoolSize">100</property>
    <property name="hibernate.c3p0.maxIdleTime">1200</property>
    <property name="hibernate.c3p0.maxStatements">50</property>
    <property name="hibernate.c3p0.minPoolSize">10</property>-->  

My connection pooling is occurring fine. During the day it is fine , but once i keep it idle over the night ,next day I find it giving me broken connection error.

public class HibernateUtil {

private static Logger log = Logger.getLogger(HibernateUtil.class);
//private static Log log = LogFactory.getLog(HibernateUtil.class);

private static Configuration configuration;
private static SessionFactory sessionFactory;

static {
    // Create the initial SessionFactory from the default configuration files
    try {

        log.debug("Initializing Hibernate");

        // Read hibernate.properties, if present
        configuration = new Configuration();
        // Use annotations: configuration = new AnnotationConfiguration();

        // Read hibernate.cfg.xml (has to be present)
        configuration.configure();

        // Build and store (either in JNDI or static variable)
        rebuildSessionFactory(configuration);

        log.debug("Hibernate initialized, call HibernateUtil.getSessionFactory()");
    } catch (Throwable ex) {
        // We have to catch Throwable, otherwise we will miss
        // NoClassDefFoundError and other subclasses of Error
        log.error("Building SessionFactory failed.", ex);
        throw new ExceptionInInitializerError(ex);
    }
}

/**
 * Returns the Hibernate configuration that was used to build the SessionFactory.
 *
 * @return Configuration
 */
public static Configuration getConfiguration() {
    return configuration;
}

/**
 * Returns the global SessionFactory either from a static variable or a JNDI lookup.
 *
 * @return SessionFactory
 */
public static SessionFactory getSessionFactory() {
    String sfName = configuration.getProperty(Environment.SESSION_FACTORY_NAME);
    System.out.println("Current s name is "+sfName);
    if ( sfName != null) {
        System.out.println("Looking up SessionFactory in JNDI");
        log.debug("Looking up SessionFactory in JNDI");
        try {
            System.out.println("Returning new sssion factory");
            return (SessionFactory) new InitialContext().lookup(sfName);
        } catch (NamingException ex) {
            throw new RuntimeException(ex);
        }
    } else if (sessionFactory == null) {
        System.out.println("calling rebuild session factory now");
        rebuildSessionFactory();
    }
    return sessionFactory;
}

/**
 * Closes the current SessionFactory and releases all resources.
 * <p>
 * The only other method that can be called on HibernateUtil
 * after this one is rebuildSessionFactory(Configuration).
 */
public static void shutdown() {
    log.debug("Shutting down Hibernate");
    // Close caches and connection pools
    getSessionFactory().close();

    // Clear static variables
    sessionFactory = null;
}


/**
 * Rebuild the SessionFactory with the static Configuration.
 * <p>
 * Note that this method should only be used with static SessionFactory
 * management, not with JNDI or any other external registry. This method also closes
 * the old static variable SessionFactory before, if it is still open.
 */
 public static void rebuildSessionFactory() {
    log.debug("Using current Configuration to rebuild SessionFactory");
    rebuildSessionFactory(configuration);
 }

/**
 * Rebuild the SessionFactory with the given Hibernate Configuration.
 * <p>
 * HibernateUtil does not configure() the given Configuration object,
 * it directly calls buildSessionFactory(). This method also closes
 * the old static variable SessionFactory before, if it is still open.
 *
 * @param cfg
 */
 public static void rebuildSessionFactory(Configuration cfg) {
    log.debug("Rebuilding the SessionFactory from given Configuration");
    if (sessionFactory != null && !sessionFactory.isClosed())
        sessionFactory.close();
    if (cfg.getProperty(Environment.SESSION_FACTORY_NAME) != null) {
        log.debug("Managing SessionFactory in JNDI");
        cfg.buildSessionFactory();
    } else {
        log.debug("Holding SessionFactory in static variable");
        sessionFactory = cfg.buildSessionFactory();
    }
    configuration = cfg;
 }

}

Above is my code for the session factory. And I have only select operations .

And below is the method which is used most often to execute my select queries. One tricky thing which I am not understanding is in my findById method i am using this line of code getSession().beginTransaction(); without which it gives me an error saying that this cannot happpen without a transaction. But nowhere I am closing this transaction. And thers no method to close a transaction apart from commit or rollback (as far as i know) which are not applicable for select statements.

public T findById(ID id, boolean lock) throws HibernateException, DAOException {
log.debug("findNyId invoked with ID ="+id+"and lock ="+lock);
T entity;
getSession().beginTransaction();

    if (lock)
        entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
    else
        entity = (T) getSession().load(getPersistentClass(), id);

    return entity;
}

Can anyone please suggest what can I do ? I have tried out almost every solution available via googling, on stackoverlow or on hibernate forums with no avail. (And increasing wait_timeout on mysql is not a valid option in my case).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吾性傲以野 2024-09-09 05:37:55

我知道 MySQL 可以在“n”小时不使用后使连接失效(请参阅 此处)供参考。

那么您可以配置 C3P0 在将连接提供给您(客户端)之前验证连接吗?或者配置 C3P0 在一定时间后超时连接?有关详细信息,请参阅此链接

I understand that MySQL can invalidate connections after 'n' hours of no use (see here) for a reference.

So can you configure C3P0 to validate a connection before giving it to you (the client) ? Or configure C3P0 to time out connections after a certain time ? See this link for more info.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文