管理 Java servlet 的数据库连接的最佳方式

2022-09-01 15:36:38

在 Java servlet 中管理数据库连接的最佳方法是什么?

目前,我只是在函数中打开一个连接,然后在.init()destroy()

但是,我担心“永久”保持数据库连接可能是一件坏事。

这是处理这个问题的正确方法吗?如果没有,有哪些更好的选择?

编辑:为了进一步澄清:我尝试简单地为每个请求打开/关闭一个新连接,但是在测试中,由于创建太多连接,我看到了性能问题。

通过多个请求共享连接有什么价值吗?对此应用程序的请求几乎都是“只读”的,并且来得相当快(尽管请求的数据相当小)。


答案 1

正如大家所说,您需要使用连接池。为什么?怎么回事?等。

您的解决方案出了什么问题

我知道这一点,因为我也曾认为这是一个好主意。问题是双重的:

  1. 所有线程(servlet 请求的每个线程都有一个线程)将共享相同的连接。因此,请求将一次处理一个。这是非常慢的,即使你只是坐在一个浏览器中并依靠F5键。试试吧:这些东西听起来很高级和抽象,但它是经验性的和可测试的。
  2. 如果连接因任何原因中断,则不会再次调用 init 方法(因为 servlet 不会停止服务)。不要试图通过在doGet或doPost中放置一个尝试来解决这个问题,因为那样你就会陷入地狱(有点像在没有被要求的情况下编写应用程序服务器)。
  3. 与人们的想法相反,你不会有事务问题,因为事务开始与线程相关联,而不仅仅是连接。我可能是错的,但由于这是一个糟糕的解决方案,所以不要出汗。

为什么选择连接池

连接池为您提供了一大堆优势,但最重要的是它们解决了

  1. 建立真正的数据库连接成本高昂。连接池周围总是有一些额外的连接,并为您提供其中之一。
  2. 如果连接失败,连接池知道如何打开一个新连接池
  3. 非常重要:每个线程都有自己的连接。这意味着线程在它应该在的地方处理:在数据库级别。数据库效率超高,可以轻松处理并发请求。
  4. 其他东西(如JDBC连接字符串的集中位置等),但是有数百万篇文章,书籍等。

何时获取连接

在服务委托(doPost,doGet,doDisco等)中启动的调用堆栈中的某个位置,您应该获得一个连接,然后您应该做正确的事情并在最终的块中返回它。我应该提到,C#主架构师家伙一次说过,你应该使用块比块多100倍。从未说过的更真实的话...finallycatch

哪个连接池

您位于 servlet 中,因此应使用容器提供的连接池。您的 JNDI 代码将完全正常,除了您如何获取连接。据我所知,所有 servlet 容器都有连接池。

关于上述答案的一些评论建议改用特定的连接池 API。您的 WAR 应该是可移植的,并且“只需部署”。我认为这基本上是错误的。如果您使用容器提供的连接池,那么您的应用程序将可以部署在跨多台计算机的容器上,以及 Java EE 规范提供的所有花哨的东西。是的,必须编写特定于容器的部署描述符,但这是EE方式,mon。

一位评论者提到,某些容器提供的连接池不适用于 JDBC 驱动程序(他/她提到了 Websphere)。这听起来完全是牵强附会和荒谬的,所以这可能是真的。当这样的事情发生时,把你“应该做”的所有事情都扔进垃圾箱,尽你所能。这就是我们得到的报酬,有时:)


答案 2

我实际上不同意使用Commons DBCP。您确实应该遵从容器来为您管理连接池。

由于您使用的是 Java Servlet,这意味着在 Servlet 容器中运行,而我熟悉的所有主要 Servlet 容器都提供连接池管理(Java EE 规范甚至可能需要它)。如果你的容器碰巧使用DBCP(就像Tomcat一样),那就太好了,否则,只需使用容器提供的任何内容。


推荐