我应该如何使用 java servlet、JSP 和 JSP 管理与数据库的连接?雄猫

发布于 2024-09-18 12:23:09 字数 1120 浏览 5 评论 0原文

我对 Servlet 和 JSP 以及使用数据库还很陌生。

目前,我的网络应用程序的“模型”部分有一个类,其中有很多我编写的用于执行数据库查询和更新的方法。目前,在每个方法中,我都创建一个数据库连接,执行 SQL 操作,然后关闭连接。

当我只是为自己制作小型应用程序时,这工作得很好,但我开始意识到,如果很多人同时使用我的应用程序,那么创建数据库连接并为每个方法调用关闭它们就会开始变得明显时间成本高昂的过程。所以我需要改变我做事的方式。

在 Head First Servlet 中JSP 由 Basham、Sierra 和 JSP 提供Bates 描述了如何使用 ServletContextListener 实现在 Web 应用程序的部署上创建一个对象,该对象将作为 ServletContext 的属性添加。作者没有深入讨论,但暗示人们经常添加数据库连接作为 ServletContext 的属性。我想我想自己实现这个,但是在阅读 这篇有关数据库连接管理的 stackoverflow 文章 我不太确定。

然而,由于我刚刚开始接触 servlet 和 JSP,更不用说 J2EE 的其余部分,所以那篇文章的很多内容都超出了我的能力范围。

该文章中对我来说最突出的一点是:

  • 可能会发生某些事情破坏该数据库连接,如果我们仅依赖该连接,那么我们需要重新部署我们的应用程序才能重新启动连接。这是正确的吗?

  • 我们应该回复容器来为我们管理数据库连接。太好了,但是这是如何实现的呢?如何与容器通信? (请记住,我刚刚开始使用 Servlet 和 JSP)。

  • 就一般的 Servlet 设计而言,我对每种请求类型都有一个 Servlet 类,并且通常只有一种类型的数据库调用,即特定的更新或查询。与使用包含所有查询数据库方法的类相比,将这些方法放在各自的 servlet 中对我来说是更好的设计还是会违反模型-视图-控制器模式?

我无法想象我会遇到太多的问题,太多的用户会减慢用户体验:)但如果可能的话,我想开始做正确的事情。

非常感谢您的评论

I'm pretty new to Servlets and JSP and to using databases.

At the moment I have a class in the 'model' part of my web app which has lots of methods that I've written to perform database queries and updates. At the moment, in each of those methods I am creating a database connection, doing the SQL stuff, then closing the connection.

This works fine while I'm just making small apps for myself but I'm starting to realise that if lots of people were using my app concurrently then it would start to become apparent that creating database connections and closing them for each method call is a time costly process. So I need to change the way I do things.

In Head First Servlet & JSP by Basham, Sierra & Bates, they describe how it's possible to use a ServletContextListener implementation to create an object on the deployment of the web app that will be added as an attribute of the ServletContext. The authors don't go into it, but imply that people often add a database connection as an attribute of the ServletContext. I thought I would like to implement this for myself, but after reading this stackoverflow article on database connection management I'm not so sure.

However as I'm just starting with servlets and JSP, let alone the rest of J2EE, a lot of that article is beyond me.

The points that stand out for me from that article are:

  • Something could happen to break that database connection and if we are relying only on that connection then we would need to redeploy our app in order to restart a connection. is this correct?

  • We should reply on the container to manage the database connections for us. Great, but how is this acheived? How can I communicate with the container? (Please bear in mind that I've just started with Servlets and JSP).

  • In terms of Servlet design in general, I have one servlet class per request type and that normally only has one type of call to a database ie a specific update or query. Instead of having a class with all the methods for querying the database, is it a better design for me to have the methods within their respective servlets or would that contravene the Model-View-Controller pattern?

I can't imagine that I'll be having too many problems with too many users slowing down the user experience just yet :) but I'd like to start doing things right if possible.

Many thanks in advance for your comments

Joe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

痴情换悲伤 2024-09-25 12:23:09

Tomcat 网站上的以下页面介绍了如何操作详细连接Tomcat和mySQL。您不想推出自己的数据源池,已经有太多可用的数据源池已经在生产环境中进行了调试和尝试。

使用池的主要一点是,当您调用 close 时,连接不会终止,而是只是返回到池中。因此,确保在 try/finally 块中关闭资源非常重要。 在此处查看示例

The following page on Tomcat's website describes how to connect Tomcat and mySQL in detail. You do not want to roll your own, there are too many DataSource pools already available that have been debugged and tried in production environments.

The main thing about using a pool is that a connection is not terminated when you call close, instead it is just returned to the pool. Therefore it is important to make sure that you close your resources in a try/finally block. Look here for a sample.

白龙吟 2024-09-25 12:23:09

我会检查连接池,特别是像 C3P0Apache Commons DBCP

这两个包都会为您维护和管理数据库连接的集合。

通常,连接是提前建立的,并在请求线程需要时分发给它们。连接可以在分发之前进行验证(如果连接断开,则可以在客户端使用它们之前重新建立连接)。

I would check out connection pooling and specifically frameworks like C3P0 or Apache Commons DBCP.

Both these packages will look after maintaining and managing a collection of database connections for you.

Typically connections are established in advance, and handed out to requesting threads as they require them. Connections can be validated prior to being handed out (and remade in advance of the client using them if the connection is broken).

暮色兮凉城 2024-09-25 12:23:09

Web 应用程序的方法是让连接池管理您的连接。这将允许您的执行线程共享数据库连接,这一点很重要,因为连接到数据库通常是一项成本高昂的操作。使用连接池通常只是一项配置任务,因为大多数容器都支持管理连接池。

从代码的角度来看,几乎没有什么变化。基本上:

  • 连接池是通过 DataSource 接口访问的,而非池连接可以通过旧的 DriverManager 访问。
  • 要获取DataSource,您通常必须使用 JNDI,因为这是在 J2EE 应用程序中发布连接池的标准方法。
  • 您希望尽快关闭 close() Connection 对象。这会将连接返回到池中,而无需断开与数据库的连接,以便其他线程可以使用它。

与往常一样,您应该对每个 JDBC 资源(连接、语句、结果集)调用 close() 以避免泄漏。这在服务器应用程序中特别重要,因为它们很少重新启动,因此泄漏会随着时间的推移而积累,最终会使您的应用程序出现故障。

这是来自 http:// 的一些示例代码download.oracle.com/javase/1.4.2/docs/guide/jdbc/getstart/datasource.html(注意:非异常安全)。正如您所看到的,一旦获得Connection 引用,就没有什么特别的了。

Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("jdbc/AcmeDB");
Connection con = ds.getConnection("genius", "abracadabra");
con.setAutoCommit(false);
PreparedStatement pstmt = con.prepareStatement(
                            "SELECT NAME, TITLE FROM PERSONNEL WHERE DEPT = ?");
pstmt.setString(1, "SALES");
ResultSet rs = pstmt.executeQuery();

System.out.println("Sales Department:");
while (rs.next()) {
        String name = rs.getString("NAME");
        String title = rs.getString("TITLE");
        System.out.println(name + "  ; ;" + title);
}
pstmt.setString(1, "CUST_SERVICE");
ResultSet rs = pstmt.executeQuery();

System.out.println("Customer Service Department:");
while (rs.next()) {
        String name = rs.getString("NAME");
        String title = rs.getString("TITLE");
        System.out.println(name + "  ; ;" + title);
}
rs.close();
pstmt.close();
con.close();

The way to go in a web application is to have a connection pool manage your connections. This will allow your threads of execution to share the database connections, which is an important point as connecting to a database is usually a costly operation. Using a connection pool is usually just a configuration task as most containers support managing a connection pool.

From the viewpoint of your code, there are very few changes. Basically:

  • Connection pools are accessed through the DataSource interface, while non-pooled connections may be accessed through the old DriverManager.
  • To get the DataSource you will usually have to use JNDI, as this is the standard method for publishing connection pools in a J2EE application.
  • You want to close() Connection objects as soon as possible. This returns the connection to the pool wothout disconnecting from the DB, so that other threads can use it.

As always, you should call close() on every JDBC resource (connections, statements, resultsets) to avoid leaking. This is specially important in a server application because they are infrequently restarted so leaks accumulate over time and eventually will make your application malfunction.

This is some example code from http://download.oracle.com/javase/1.4.2/docs/guide/jdbc/getstart/datasource.html (NOTE: not exception-safe). As you can see, once you get the Connection reference there is nothing really special.

Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("jdbc/AcmeDB");
Connection con = ds.getConnection("genius", "abracadabra");
con.setAutoCommit(false);
PreparedStatement pstmt = con.prepareStatement(
                            "SELECT NAME, TITLE FROM PERSONNEL WHERE DEPT = ?");
pstmt.setString(1, "SALES");
ResultSet rs = pstmt.executeQuery();

System.out.println("Sales Department:");
while (rs.next()) {
        String name = rs.getString("NAME");
        String title = rs.getString("TITLE");
        System.out.println(name + "  ; ;" + title);
}
pstmt.setString(1, "CUST_SERVICE");
ResultSet rs = pstmt.executeQuery();

System.out.println("Customer Service Department:");
while (rs.next()) {
        String name = rs.getString("NAME");
        String title = rs.getString("TITLE");
        System.out.println(name + "  ; ;" + title);
}
rs.close();
pstmt.close();
con.close();
泪痕残 2024-09-25 12:23:09

作者没有深入探讨,但暗示人们经常添加数据库连接作为 ServletContext 的属性。

这不是处理这个问题的标准方法。传统方法是使用连接池,即准备使用的连接池。然后,应用程序从池中借用连接并在完成后将它们返回到池中。

有多种可用的独立连接池实现(C3P0、Commons DBCP、Bone CP),您可以将它们捆绑到应用程序中。但是当使用Servlet或Java EE容器时,我会使用容器提供的连接池。然后,通过 JNDI 从应用程序获取 DataSource(连接池上的句柄),以从中获取 JDBC 连接(并关闭它以将其返回到池中)。

配置池的方法显然是特定于容器的,因此您需要参考容器的文档。好消息是 Tomcat 提供了几个示例 展示如何执行此操作、如何通过 JNDI 获取数据源以及如何编写正确的 JDBC 代码(请阅读到页面底部)。

参考

The authors don't go into it, but imply that people often add a database connection as an attribute of the ServletContext.

That's not the standard way to handle this. The traditional approach is to use a connection pool i.e. a pool of ready to use connections. Then, applications borrow connections from and return them to the pool when done.

There are several standalone connection pool implementations available (C3P0, Commons DBCP, Bone CP) that you can bundle in your application. But when using a Servlet or Java EE container, I would use the connection pool provided by the container. Then, obtain a DataSource (a handle on a connection pool) via JNDI from the application to get a JDBC connection from it (and close it to return it to the pool).

The way to configure a pool is obviously container specific so you need to refer to the documentation of your container. The good news is that Tomcat provides several examples showing how to do this, how to obtain a datasource via JNDI and how to write proper JDBC code (read until the bottom of the page).

References

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文