【问题标题】:Sharing database connection with static methods in Java使用 Java 中的静态方法共享数据库连接
【发布时间】:2013-10-17 20:10:44
【问题描述】:

我正在使用 Struts 2 开发一个 java web 应用程序。目前,在每个页面加载时,我都会建立一个新的数据库连接,然后在请求结束时关闭这个数据库连接,就在呈现结果 HTML 之前。因此,每个请求都有自己的数据库连接。

我想在我的模型类中包含一堆静态方法,例如 User.exists( id ) 这样的东西,如果给定的用户 ID 存在则返回 true,否则返回 false。或其他实用方法,如 User.getEmail(id)User.disable(id)

我的问题是,有没有一种方便的方法可以与这些静态方法共享数据库连接?必须将连接作为所有这些方法的第二个参数传递,例如 User.exists(id, db) 会很丑陋,而且不太方便。

如果我在这些实用方法中的每一个中获得一个新的数据库连接,并在返回结果之前关闭它会怎样?会不会对性能有影响?有时我可能需要在一个请求中调用这些方法 20-30 次(例如在验证用户输入时)。

【问题讨论】:

  • 仅当您的数据库连接是完全线程安全的时,这是不太可能的。使用连接池。
  • @SLaks 我正在使用 struts 拦截器,它在每个页面请求开始时由 struts 调用。 db 连接是在拦截器的intercept() 方法中建立的,并且也在相同的方法中关闭,它知道请求已经完成渲染。所以我认为我在线程方面是安全的。我关心的是在每个静态实用程序方法中建立新的连接。这会影响性能吗?
  • 如果您使用的是 JEE 应用程序服务器,请使用它的连接池工具。然后你可以实现一个 OSIV 拦截器,如果使用 Spring/hibernate,它只需要一个动作来建立一个事务会话。事务会话只会在拦截器展开时关闭,但如果不需要数据库访问,则无需花费时间打开与数据库的实际连接。

标签: java mysql design-patterns struts2 connection-pooling


【解决方案1】:

是的,这是可能的。对于这种您希望每个线程都有自己的连接的情况,您需要使用ThreadLocal,因为每个请求都会产生自己的线程。您只需要确保在请求结束时关闭连接,这是使用Filter 实现的。

过滤器应该在任何其他过滤器之前,以确保连接在请求结束时关闭。

DBUtil:

public class DBUtil {

    private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();

    public static Connection getConnection() {
        Connection connection = connectionHolder.get();
        if (connection == null) {
            //open the connection (lazy loaded)

            //store it
            connectionHolder.set(connection);

        }
        return connectionHolder.get();
    }

    public static void close() {
        Connection connection = connectionHolder.get();
        if (connection != null) {
            //close the connection

            //remove it from the connection holder
            connectionHolder.remove();
        }
    }

}

DBFilter

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {       
    try {
        chain.doFilter(request, response);
    } finally {
        DBUtil.close();         
    }
}

如果你为这类事情使用框架会更好,例如Spring Framework 已经通过代理你的服务来做到这一点,它处理连接和事务还为你提供了许多其他功能。

【讨论】:

  • 有趣,所以你说我可以有一个 ThreadLocal 数据库连接,然后每次我调用Db.getConnection(),它只会返回当前请求的唯一/本地数据库连接?如果是这样,您能否提供有关如何实现它的更多详细信息,例如在过滤器中?然后我可以接受。
  • @ClickUpvote 完成。无论如何,我建议使用更完整的东西,例如 Spring,它为您提供了此功能和 Transaction 功能,因此您无需自己制作。
  • 谢谢。你熟悉Struts吗? Struts 2 有一个ActionContext,它似乎是线程安全的..
  • @ClickUpvote 没错,ActionContext 也使用 ThreadLocal,这就是它是线程安全的原因。
  • 或许您可以在这里回答我的问题? stackoverflow.com/questions/19437095/…
猜你喜欢
  • 2012-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 2023-03-03
  • 1970-01-01
  • 2021-09-28
相关资源
最近更新 更多