使用JNDI进行数据库连接

4
这可能听起来像一个初学者的问题,但这是我第一次涉足数据库领域。
这里我得到的信息是:

实现服务器和数据库之间通信的最有效方法是设置数据库连接池。为每个客户端请求创建一个新连接可能非常耗时,特别是对于持续接收大量请求的应用程序。

而且该教程使用了JNDI数据源。

我的应用程序也类似(但我不会使用Tomcat,只使用套接字),我的服务器将从多个客户端接收请求,但我不明白为什么我应该使用JNDI数据源,为什么服务器不能与数据库保持一个打开的连接,并在客户端请求到达时处理请求并向客户端提供数据。

在最坏的情况下,如果我需要JNDI,我该如何在我的服务器应用程序中实现它?

4个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
4
因此,它是一个客户端应用程序吗?应用程序和数据库通常使用DriverManager#getConnection()获得的连接进行通信?如果是这样,那么您不一定需要JNDI来使连接池工作。单独的连接池框架已经足够了。例如C3P0Apache Commons DBCP(我建议使用C3P0;DBCP是单线程的)。只需将DriverManager#getConnection()替换即可。

编辑:回复您的评论:

服务器将与数据库通信,客户端连接到服务器,因此我不知道是否应将其称为客户端应用程序。

实际上,我指的是一个简单的纯Java应用程序,不运行在Java EE容器中。Pascal表达得更好。

实际上,我有点困惑连接池是如何工作的,每个连接是否在自己的线程中运行?是否有任何文档/书籍可以帮助我更好地理解这些概念,与非池化连接相比?

首先,连接池会打开一个连接并将其保持打开状态,直到配置的超时时间。连接池使用自己的实现包装/修饰该连接。连接池可以同时打开和保持配置数量的连接。当您调用getConnection()时,它会立即给您一个已经打开的连接。当您在连接上调用close()时,它会将连接放回池中以供未来的请求使用。因此这意味着您仍然需要按照通常的方式编写JDBC代码:在最短的可能范围内获取和关闭ConnectionStatementResultSet。在finally块中关闭它们。如果您的JDBC代码已经很好地编写了,事实上只需要替换DriverManager#getConnection()。由于您应该在同一方法块中打开和关闭Connection,因此它通常会在同一线程中运行。连接池将关心Connection在此期间是否被其他线程获取,直到您的代码在Connection上调用close()。 你可以在这里找到一篇很好的文章,以了解连接池是如何在底层工作的(请注意:不要将其用于生产环境,也不要进一步自行开发它,仅仅是为了获得整体概念)。对于真正的工作,请使用现有的经过彻底开发和强大的连接池框架。

服务器将与数据库通信,客户端连接到服务器,因此我不知道是否应将其称为客户端应用程序。是的,代码的服务器部分正在使用DriverManager.getConnection(),感谢提供C3P0链接。 - Kevin Boyd
感谢您清晰、简明的解释,我已经使用DriverManager编写了一些示例代码,但是我一直保持连接处于打开状态。我的客户端正在使用套接字连接到服务器,并将保持连接。每个客户端都在自己的读/写线程中运行,因此如果服务器想要传递数据,它只需从数据库中请求数据(从已经打开的连接)并将其传递给所述客户端。这是正确的方法还是应该尽快关闭连接? - Kevin Boyd
2
通常的做法是在 finally 块中关闭连接,以避免资源泄漏和/或潜在的应用程序崩溃,假如您打开了多个连接,并且/或数据库超时连接。为了提高连接性能,最好的方法是使用连接池。只需确保不要将连接池的超时配置(即保持连接打开的时间)设置得比数据库自己的连接超时更长即可。 - BalusC

2
我的应用程序也类似(但我不会使用Tomcat,只是套接字),我的服务器将从多个客户端收到请求,但我不明白为什么我应该使用JNDI数据源,为什么不能让服务器与数据库维护一个开放的连接,并在客户端请求到达时处理请求并向客户端提供数据。 嗯,你可以这样做。但是如果您有多个客户端并且必须服务于并发请求怎么办?当然,您可以为每个客户端维护一个打开的连接,但这并不真正扩展(这在您的上下文中可能不是问题)。仍然,解决此问题的传统方法是使用连接池(并从额外的服务中受益,例如连接验证、连接更新),并使用它来根据需要获取连接。 如果您不处于J2EE容器上下文中,请使用独立的连接池实现,例如c3p0(优先选择c3p0而不是被认为已过时且在负载下不太稳定的DBCP),并忘记JNDI(这只是在您运行时获取连接池句柄的标准方式 J2EE容器内部)。 请查看c3p0的文档documentation以获取更多细节和代码示例,非常清晰明了。

我不知道JNDI只在J2EE容器的上下文中使用,感谢您提醒我,并且还感谢您提供c3p0和DBCP链接。 - Kevin Boyd
实际上我对连接池的工作原理有点困惑,每个连接是否在自己的线程中运行?是否有任何文档/书籍可以帮助我更好地了解这些概念,特别是与未池化连接相比? - Kevin Boyd

2

JNDI用于数据库连接,解决了应用程序开发人员不是管理数据库连接的人的情况。

因此,应用程序开发人员可以指定他们的应用程序需要多少同时连接。然后,服务器管理员会定义数据库连接池。应用程序查找该池。

应用程序和应用程序开发人员都不需要知道连接到数据库所需的凭据。另外,服务器管理员可以根据部署环境定义不同大小的连接池,应用程序也与这些差异无关。

由于你的应用程序本身就是服务器,因此应用程序负责定义和管理与数据库的连接。


应用程序开发人员如何判断同时连接的数量?如果应用程序和应用程序开发人员不知道安全参数(凭据)在哪里指定,那么这些参数在哪里?它们是否加载在配置文件中? - Kevin Boyd
1
对于连接计数,一种选择是猜测并在预期的最大生产量下进行负载测试,并监视连接使用情况。使用您在负载测试中观察到的最大值的约110%。或者,您可以检查应用程序对连接的使用情况,并尝试根据访问DB的方式、同时存在的客户端数量等来做出有根据的猜测。凭据存储在应用程序服务器的配置中。服务器的处理方式不同,但它们以标准方式公开连接池,即JNDI。 - shadit

1

再提供一个连接池的链接:BoneCP(http://jolbox.com)。基准测试表明它比C3P0/DBCP更快。

P.S. 在我的多线程测试中也没有看到DBCP锁死。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,