为什么同时使用C3PO和JNDI会产生问题?

时间:2016-08-18 21:49:55

标签: hibernate jndi

我正在运行一个使用Tomcat 8服务器中的Hibernate的应用程序。我想利用除Hibernate之外的其他连接池,因为它们很明显它不适合在生产环境中使用。

另外,他们提到:

  

要在应用程序服务器中使用,您几乎应该始终配置Hibernate以从JNDI中注册的应用程序服务器javax.sql.Datasource获取连接。

所以我觉得我需要做两件事:

  1. 配置Hibernate以使用第三方连接池 - Hibernate建议使用C3PO
  2. 配置Hibernate以从JNDI中注册的javax.sql.Datasource对象
  3. 获取连接

    我一直在研究如何做出这些改变,我遇到了this所以问题。海报已经在使用C3PO,并询问如何通过JNDI Datasource对象连接到他们的数据库。然而,他们遇到了问题,因为他们已经在使用C3PO,而他们正在遵循回答者使用JNDI数据源的步骤。海报在接受的答案的评论部分说了这个:

      

    是的,我在那里使用c3p0和JNDI一直很傻。我删除了所有c3p0配置,现在工作正常。

    Hibernate建议使用第三方连接池,即C3PO,并使用JNDI数据源来接收连接,但它似乎对该用户造成了问题;他们甚至谈到同时使用它们就好像这是一个明显的错误。

    所以我不能同时使用它们,或者我应该像Hibernate推荐的那样使用它们吗?我所要做的就是将Hibernate的默认连接池替换为打算在生产环境中使用的池,并将Hibernate配置为从JNDI中注册的javax.sql.Datasource对象获取连接,如他们所推荐的那样。 / p>

2 个答案:

答案 0 :(得分:4)

我会尽力清理混乱。

我认为它从简单的DataSource接口开始:https://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html

  

DataSource接口由驱动程序供应商实现。有   三种类型的实现:

     
      
  1. 基本实现 - 生成标准Connection对象
  2.   
  3. 连接池实现 - 生成一个将自动参与连接池的Connection对象。这个   实现适用于中间层连接池管理器。
  4.   
  5. 分布式事务实现 - 生成一个可用于分布式事务的Connection对象,几乎总是如此   参与连接池。这个实现适用于   中间层事务管理器,几乎总是有连接   合并经理。
  6.   

Hibernate需要使用DataSource,并建议它使用连接池。

C3PO包装现有的DataSource并对其应用连接池,并创建一个类型为2的新DataSource.C3PO假定它获取的DataSource是类型1,但无法确定。

在其他应用程序服务器中,如果声明在JNDI中注册的数据源,它几乎总是使用容器中已有的连接池。对于Tomcat 8,它在内部使用C3PO。

因此,有两种方法可以在Hibernate中实现连接池:创建类型1数据源并将其嵌入到代码中的连接池中,或者在容器中声明数据源(带连接池),并将其从hibernate中注入JNDI。

如果您同时执行这两项操作,则应用程序中的C3PO会从JNDI获取数据源,而JNDI本身就是由tomcat管理的C3PO数据源。当应用程序尝试获取连接时,应用程序C3PO将调用容器C3PO,这将创建实际连接,但连接将在两个连接池中池化。当hibernate释放连接时,应用程序C3PO将保留它以供重用,但另一个连接池将继续等待连接被释放。

根据配置的不同,底层连接池可能会在超时后终止连接。

因此,将两个连接池相互配置是危险的,完全没必要。

回答赏金问题:在生产环境中,在生产容器中声明数据源,并通过JNDI将其连接到Hibernate,而不在Hibernate中配置任何其他连接池。

答案 1 :(得分:1)

在参考SO帖子中,海报从已经由Hibernate配置的C3PO开始。当海报移动到获得对已配置的 C3PO连接池的JNDI引用时,他/她认为Hibernate在启动期间正在处理配置。解决方案是将C3PO配置移动到容器(Tomcat)并从Hibernate设置中删除配置。

以下是应用程序启动的简要概述:

  • Container执行其启动操作
    • 创建连接并开始侦听连接
    • 创建和配置JNDI资源,如DataStore&,邮件会话等
  • 部署Web应用程序
    • 扫描网络应用程序
    • 配置Web应用程序
    • 提供配置期间指定的任何JNDI资源
    • 完成部署

在Web应用程序部署阶段,读取Hibernate配置并发出JNDI资源请求。由于已经配置了C3PO,因此不会看到在Hibernate中完成的任何配置。