在Java servlet中管理数据库连接的最佳方法是什么?
目前,我只是在init()
函数中打开一个连接,然后在destroy()
中将其关闭。
然而,我担心“永久”持有数据库连接可能是件坏事。
这是处理此问题的正确方法吗?如果没有,有什么更好的选择?
编辑:进一步澄清一下:我尝试过为每个请求打开/关闭一个新连接,但是通过测试我发现由于创建了太多连接而导致性能问题。
在多个请求中共享连接有什么价值吗?对此应用程序的请求几乎都是“只读”并且速度非常快(尽管请求的数据相当小)。
答案 0 :(得分:22)
正如大家所说,你需要使用连接池。为什么?怎么了?等
您的解决方案有什么问题
我知道这一点,因为我以前认为这是一个好主意。问题是双重的:
为什么选择连接池
连接池为您提供了许多优势,但最重要的是它们解决了
的问题何时获取连接
在您的服务委托(doPost,doGet,doDisco,无论如何)中启动的调用堆栈中的某个地方,您应该获得连接,然后您应该做正确的事情并将其返回到finally块中。我应该提一下,C#主建筑师老兄曾说过,你应该使用finally
块比catch
块多100倍。真正的话从未说过......
哪个连接池
您在servlet中,因此您应该使用容器提供的连接池。除了获得连接的方式之外,您的JNDI代码将完全正常。据我所知,所有servlet容器都有连接池。
上述答案的一些评论建议使用特定的连接池API。您的WAR应该是可移植的并且“只是部署”。我认为这基本上是错误的。如果您使用容器提供的连接池,您的应用程序将可以部署在跨多台计算机的容器上,以及Java EE规范提供的所有那些花哨的东西。是的,必须编写特定于容器的部署描述符,但这是EE方式,mon。
一位评论者提到某些容器提供的连接池不能与JDBC驱动程序一起使用(他/她提到了Websphere)。这听起来完全是牵强附会和荒谬的,所以它可能是真的。当这样的事情发生时,把你应该做的所有事情扔进垃圾桶,尽你所能。这就是我们得到的报酬,有时候:)
答案 1 :(得分:14)
我实际上不同意使用Commons DBCP。您应该真的按照容器来管理连接池。
由于您正在使用Java Servlet,这意味着在Servlet容器中运行,并且我熟悉的所有主要Servlet容器都提供连接池管理(Java EE规范甚至可能需要它)。如果你的容器碰巧使用DBCP(就像Tomcat那样),那么,不管怎么说,只需使用容器提供的任何内容。
答案 2 :(得分:4)
我会使用Commons DBCP。这是一个Apache项目,可以为您管理连接池。
您只需在doGet中获取连接,或者doPost运行查询,然后在finally块中关闭连接。 (con.close()只是将它返回到池中,它实际上并不关闭它。)
DBCP可以管理连接超时并从中恢复。如果您的数据库在任何时间段内出现故障,您当前正在做的事情就是您必须重新启动应用程序。
答案 3 :(得分:2)
你在汇集你的联系吗?如果没有,您可能应该减少打开和关闭连接的开销。
一旦完成,只要按照需要保持连接打开,就像John建议的那样。
答案 4 :(得分:2)
最好的方法,也就是我目前正在通过Google寻找更好的参考表,就是使用游泳池。
在初始化时,您将创建一个池,其中包含数据库的X个SQL连接对象。将这些对象存储在某种List中,例如ArrayList。这些对象中的每一个都有一个'isLeased'的私有布尔值,上次使用的时间很长,还有一个Connection。无论何时需要连接,都可以从池中请求连接。池将为您提供第一个可用连接,检查isLeased变量,或者它将创建一个新连接并将其添加到池中。确保设置时间戳。完成连接后,只需将其返回到池中,池将isLeased设置为false。
为了避免不断地连接数据库,您可以创建一个工作线程,该线程偶尔会通过池并查看上次使用连接的时间。如果它足够长,它可以关闭该连接并将其从池中删除。
使用它的好处是,您没有等待连接对象连接到数据库的漫长等待时间。您已建立的连接可以根据需要重复使用。并且您将能够根据您认为应用程序的繁忙程度来设置连接数。
答案 5 :(得分:1)
您应该只在需要时保持数据库连接处于打开状态,这取决于您正在执行的操作可能属于doGet/doPost
方法的范围。
答案 6 :(得分:1)
与数据源关联的连接池应该可以解决问题。您可以在servlet请求方法(doget
/ dopost
等)中获取dataSource的连接。
dbcp,c3p0和许多其他连接池可以满足您的需求。在汇集连接时,您可能希望汇总语句和PreparedStatements;此外,如果您指的是READ HEAVY环境,您可能希望使用ehcache之类的东西来缓存一些结果。
BR,
〜A
答案 7 :(得分:1)
汇集它。
此外,如果您正在使用原始JDBC,您可以查看一些可以帮助您管理Connection,PreparedStatement等的内容。除非您有非常严格的“轻量级”要求,否则使用Spring的JDBC支持将会简化你的代码很多 - 你不会被迫使用Spring的任何其他部分。
请参阅此处的一些示例:
http://static.springframework.org/spring/docs/2.5.x/reference/jdbc.html
答案 8 :(得分:0)
通常,您会发现每个请求的开放连接更易于管理。这意味着在servlet的doPost()或doGet()方法中。
在init()中打开它使所有请求都可用,并且当你有并发请求时会发生什么?