当前位置: 首页 > 面试题库 >

Hibernate:关闭会话工厂不会关闭c3p0连接池

章高爽
2023-03-14
问题内容

我最近开始在应用程序中使用hibernate和c3p0作为ORM。但是,当我关闭会话工厂时,连接池不会自行关闭!这是我的应用程序中 唯一
可以进行会话操作的地方。

    StatelessSession session = null;
    Transaction transaction = null;


    try {
        session = sessionFactory.openStatelessSession();
        transaction = session.beginTransaction();

        List<Thingy> list = session.getNamedQuery("getAvailableThingy").list();

        transaction.commit();
        return list;

    } catch (Exception error) { 
        if (transaction != null) {
            transaction.rollback();
        }
        throw error;
    } finally {
        if (session != null) {
            session.close();
        }
    }

这是我的hibernate.cfg.xml配置文件

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">


<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="javax.persistence.validation.mode">none</property>
        <property name="hibernate.connection.release_mode">after_transaction</property>

        <property name="hibernate.c3p0.minPoolSize">1</property>
        <property name="hibernate.c3p0.maxPoolSize">2</property>
        <property name="hibernate.c3p0.acquireIncrement">1</property>
        <property name="hibernate.c3p0.initialPoolSize">1</property>
        <property name="hibernate.c3p0.timeout">30</property>
        <property name="hibernate.c3p0.maxIdleTimeExcessConnections">5</property>
        <property name="hibernate.c3p0.idleConnectionTestPeriod">300</property>
    </session-factory>
</hibernate-configuration>

请注意,空闲连接非常短的原因是它是我尚未通过集成测试的唯一方法。他们经常打开和关闭会话工厂,因此我总是用尽所有连接。正如我们在项目开始时一样,从长远来看,我认为这不是一个非常可持续的策略。

需要注意的“有趣”是,尽管我将初始连接池设置为一个,但c3p0仍然尝试在启动时打开两个连接。我的猜测是某个隐藏的会话在某个地方不会关闭(但是在哪里?击败了我)。

那么,如何才能使那个烦人的连接池关闭呢?

附加信息:我如何创建和销毁会话工厂

import static com.google.common.base.Preconditions.*;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Provides;


@Singleton 
public class PostgisConnection implements Provider<SessionFactory>, AutoCloseable {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final ConnectionInfo connectionInfo;
    private SessionFactory sessionFactory = null;

    @Inject 
    public PostgisConnection(ConnectionInfo connectionInfo) {
        this.connectionInfo = connectionInfo;
    }

    public AutoCloseable open() {
        checkState(sessionFactory == null, "Connections to postgis are already open");

        logger.info("Creating sessionFactory for connection to postgis: {}", connectionInfo.getJdbcUrl());
        sessionFactory = newPostgisSessionFactory(connectionInfo);

        return this;
    }

    @Override
    public void close() throws Exception {
        try {
            if (sessionFactory != null) {
                logger.info("Closing sessionFactory for postgis: {}", connectionInfo.getJdbcUrl());
                sessionFactory.close();
                checkState(sessionFactory.isClosed(), "Session factory should be closed at this point");
            }
        } catch (Exception error) {
            logger.error("Error closing SessionFactory", error);
        }
    }

    @Provides 
    public SessionFactory get() {
        return sessionFactory;
    }

    public static SessionFactory newPostgisSessionFactory(ConnectionInfo connectionInfo) {
        Configuration configuration = configurationWith(connectionInfo);
        return configuration.buildSessionFactory(registryFrom(configuration));
    }

    private static Configuration configurationWith(ConnectionInfo connectionInfo) {
        Configuration configuration = new Configuration();
        setConnectionInfo(connectionInfo, configuration);
        configuration.addURL(PostgisConnection.class.getResource("mapping.hbm.xml"));
        configuration.configure(PostgisConnection.class.getResource("hibernate.cfg.xml"));

        return configuration;
    }

    private static void setConnectionInfo(ConnectionInfo connectionInfo, Configuration configuration) {
        configuration.setProperty("hibernate.connection.url", connectionInfo.getJdbcUrl());
        configuration.setProperty("hibernate.connection.username", connectionInfo.getUsername());
        configuration.setProperty("hibernate.connection.password", connectionInfo.getPassword());
    }

    private static ServiceRegistry registryFrom(Configuration configuration) {
        return new ServiceRegistryBuilder()
                .applySettings(configuration.getProperties())
                .buildServiceRegistry();
    }

}
  • Hibernate版本:4.1.10.Final
  • C3p0版本:0.9.1.2

问题答案:

我遇到了同样的问题,并成功使用了此错误报告中提供的解决方法:

private void closeSessionFactory(SessionFactory factory) { 
   if(factory instanceof SessionFactoryImpl) {
      SessionFactoryImpl sf = (SessionFactoryImpl)factory;
      ConnectionProvider conn = sf.getConnectionProvider();
      if(conn instanceof C3P0ConnectionProvider) { 
        ((C3P0ConnectionProvider)conn).close(); 
      }
   }
   factory.close();
}

您必须引用hibernate-c3p0-4.xx jar。



 类似资料:
  • 我正在使用Hibernate 5.0.2.Final进行数据源连接(在Tomcat 8.0.15上),并开始问自己是否不仅需要关闭会话,还需要关闭会话工厂? 现在它看起来像这样: hibernate.cfg.xml中的一些细节 以及HibernateUtil: 我不知道是否有必要在finally-block中调用这个方法,而不仅仅是关闭会话:

  • 我在上一篇文章java中试图解决我的问题。sql。SQLRecoverableException:已关闭连接。我尝试了c3p0连接。财产如下:, 在JBOSS中部署之后,我开始测试我的web。一开始,它工作得很好,甚至更快。10分钟后,继续加载并超时。当通过服务器时。日志我得到了如下一些警告消息。 请给出一些解决这个问题的想法。

  • 我有一个Java TLS客户端,它可以向服务器发送一系列请求,每个请求后面都有对服务器的响应。 但是,有许多不同的服务器。有些是“多消息”服务器,在第一个请求后保持连接打开,以便可以通过第一个连接发送后续请求。另一些是“单消息”服务器,在每条消息之后关闭连接,因此后续消息需要新的连接。客户端没有先验的方法来知道它正在与什么类型的服务器通信,也无法修复服务器。 非常希望单个消息服务能够在没有完全握手

  • 问题内容: 我有一个使用简单套接字在两个系统之间传递某些字符的应用程序。我的Java应用程序作为服务器运行。我建立了良好的连接,甚至传递了一条消息。但是,发送完一条消息后,我的连接关闭。 从我可以看出来的好像是在关闭时,套接字本身正在关闭吗?!这很不好,因为我有多个要在同一连接上发送的消息。 我吃饱了吗?如何在Java中维护此连接? 问题答案: 是的,关闭任何作家/读者将关闭他们包装的所有其他作家

  • 大家好,正在使用Spring+JPA/Hibernate+Maven并尝试从DB获取记录。所以当我朗姆酒时,我的应用程序会出现如下错误 这是一段代码

  • 问题内容: 当我按如下方式调用session.begin事务方法时: 然后我得到以下异常消息 造成此错误的原因是什么? 问题答案: 更新: 我想调用并不能保证该会话实际上是打开的。第一次,您应该使用 代替。该建议实际上与您找到的页面一致。 之前: 根据到目前为止的可用信息,我们可以得出结论,错误的原因是会话未打开;-)