mysql - 使用 C3P0 的 Hibernate 在 Oracle 上运行良好,但不关闭与 MySQL 5.6 的连接

标签 mysql oracle hibernate servlets

我正在使用 Servlet 2.4、Hibernate 4.2.4 Final、c3p0 0.9.2.1、Tomcat 7.0.42、MySQL 5.6 和 JSP。

我已经使用 Oracle 11gR2 DB 完成了开发,但后来被要求切换到 MySQL 作为数据库。

我手头有一个相当不寻常的问题。

问题是为每个单个数据库请求创建多个 MySQL 进程/连接 ,尽管发出了 SessionFactoryUtil.close();,但既没有关闭也没有返回到池中。 Oracle DB 的情况并非如此。

我在这两个不同的数据库上测试了完全相同的代码,即在执行函数/请求之后(例如:登录)

该应用程序在使用 Oracle (11gR2) 进行测试时,数据库创建了一个连接并将其用于此后的所有请求。SELECT * FROM V$RESOURCE_LIMIT给我以下输出
RESOURCE_NAME:进程
CURRENT_UTILIZATION:32
最大利用率:36
INITIAL_ALLOCATION:300
LIMIT_VALUE:300
无论有多少用户登录连接池,它都会优雅地维护它。

另一方面,当相同的应用程序在 MySQL 上运行时:
我做了一个 SHOW PROCESSLIST;在 MySQL 上显示为每个请求创建两个进程; c3p0 成功终止了一个连接,但另一个连接一直保持到数据库崩溃,因为它超过了可用的最大连接数。

我的 SessionFactoryUtil 非常简单明了,如下所示:public class SessionFactoryUtil { private static SessionFactory sessionFactory;

public static SessionFactory getSessionFactory() {
    return sessionFactory = new Configuration().configure()
            .buildSessionFactory();//deprecated method not changed due to official reason
}

public Session getCurrentSession() {
    return sessionFactory.getCurrentSession();
}

public static void close() {
    if (sessionFactory != null) {
        sessionFactory.close();
    }
    sessionFactory = null;
}

我的DAO方法如下
public User getUserByName(String userName) throws FetchException {
User user = null;
Session session = SessionFactoryUtil.getSessionFactory().getCurrentSession();
try {
    session.beginTransaction();
    user = (User) session.createQuery("from User where userName = '" + userName + "'").uniqueResult();
} catch (Exception e) {
    logger.info("UserDaoImpl -> getUserByName() : Error : " +e);
    e.printStackTrace();
} finally {
    SessionFactoryUtil.close();
}
return user;

c3p0 破坏连接的堆栈跟踪如下:
20:45:43,692 INFO com.mchange.v2.resourcepool.BasicResourcePool:1493 - A checked-out resource is overdue, and will be destroyed: com.mchange.v2.c3p0.impl.NewPooledConnection@61f31fff 20:45:43,692 INFO com.mchange.v2.resourcepool.BasicResourcePool:1496 - Logging the stack trace by which the overdue resource was checked-out. java.lang.Exception: DEBUG STACK TRACE: Overdue resource check-out stack trace. at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:555) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutAndMarkConnectionInUse(C3P0PooledConnectionPool.java:755) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:682) at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:140) at org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:84) at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:214) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:157) at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67) at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160) at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1426) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352) at com.sun.proxy.$Proxy7.beginTransaction(Unknown Source) at com.demo.access.impl.ConfDaoImp.showAllEvents(ConfDaoImp.java:939) at com.demo.business.impl.ConfServiceImpl.showAllEvents(ConfServiceImpl.java:404) at com.demo.controller.UserController.getControls(UserController.java:112) at com.demo.controller.UserController.validateUser(UserController.java:93) at com.demo.controller.UserController.process(UserController.java:42) at com.demo.controller.ApplicationServlet.process(ApplicationServlet.java:75) at com.demo.controller.ApplicationServlet.doPost(ApplicationServlet.java:53) at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at com.demo.controller.LoginFilter.doFilter(LoginFilter.java:37) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:185) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:151) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:269) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)
我已经阅读了几乎所有与这个特定场景相关的问题,但似乎没有一个有效,或者线程被中途放弃,或者我错过了一些东西;有人可以帮我解决这个问题吗?

最佳答案

你的这段代码对我有用:

public static void close() {
if(sessionFactory instanceof SessionFactoryImpl) {
      SessionFactoryImpl sf = (SessionFactoryImpl)sessionFactory;
      ConnectionProvider conn = sf.getConnectionProvider();
      if(conn instanceof C3P0ConnectionProvider) { 
        ((C3P0ConnectionProvider)conn).close(); 
      }
   }
sessionFactory.close(); }

在那之前,Tomcat 一直(正确地)提示每次热部署时的内存泄漏。谢谢!

关于mysql - 使用 C3P0 的 Hibernate 在 Oracle 上运行良好,但不关闭与 MySQL 5.6 的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19946635/

相关文章:

hibernate - 从Grails中的一对多关系中查询项目列表

java - 需要澄清有关将对象映射到数据库、注释和一对多关系的信息

python - SQL 中的 IN 语句出现问题

mysql - 当标识符不是保留字或带有空格时,为什么必须使用反引号?

arrays - 如何在PL/SQL函数中使用传递数组

oracle - talend - 指定 jndi 作为数据源

spring - 如何在 Spring Data JPA CRUDRepository 中添加缓存功能

mysql - 限制 mysql_query(select) 查找的字符

.net - 无法将 MySQL 日期/时间值转换为 System.DateTime

sql - 十进制数、to_char 和 Oracle