【问题标题】:How to properly keep a DB connection from a Connection Pool opened in JBoss如何正确保持来自 JBoss 中打开的连接池的数据库连接
【发布时间】:2013-09-11 18:55:28
【问题描述】:

我使用 JBoss AS 7.1 作为服务器,并且我的 DataSource 配置了池。我对此很陌生,所以请原谅任何新手错误......毕竟我是来这里学习的。

当客户端登录时,它会连接到数据库,我需要保持该连接(来自池)打开,直到用户注销或 HttpSession 过期。这是来自我们的数据库管理员的绝对要求。谁说他需要 DB 会话变量。我正在使用 servlet 来完成这一切。

发挥我遇到的两个主要问题的可能性:

  1. 据我所知,JBoss 自动关闭未使用的连接 => 我打开的连接返回到池中。所以这可能不是正确的道路。

  2. 如果我尝试像 this:

    这样存储/调用 Connection 对象
    private Hashtable<String, Connection> connections = new Hashtable<String, Connection>();
    
    try {
        String strDSName1 = "java:/OracleDSJNDI";
        ctx = new InitialContext();
        ds1 = (javax.sql.DataSource) ctx.lookup(strDSName1);
    
        System.out.println("Got 1'st ds.");
    
    } catch (Exception e) {
        System.out.println("ERROR getting 1'st DS : " + e);
    }
    
    connection = ds1.getConnection();
    connections.put(session.getId(), connection);
    
    conn = (Connection) connections.get(sessionID);
    

    它会抛出这个异常:

    java.sql.SQLException:连接未与托管关联 connection.org.jboss.jca.adapters.jdbc.jdk6.WrappedConnectionJDK6@dee1f37



我的问题是:如何正确保持连接打开?

谢谢

【问题讨论】:

  • 也许你能详细说明为什么需要“会话变量”?保持数据库连接似乎阻碍了 J2ee 的连接池原则......
  • 我知道这违反了 J2ee 原则...我试图维持我的情况,但数据库管理员。坚持他需要每个客户端连接的会话变量。也许出于跟踪目的。老实说,我不明白他。我告诉他会话跟踪应该是服务器应用程序的工作。不是数据库。

标签: java jboss datasource connection-pooling


【解决方案1】:

如何正确保持连接打开?

不得这样做,让连接池处理。


在幕后,连接池将在SLEEPING 状态下保持一堆数据库连接到数据库引擎(MySQL、Oracle、SQL Server...取决于您如何配置)。当你执行这段代码时:

//avoiding all the particular exceptions just for code simplicity purposes...
//in real world applications, you must handle each of these exceptions
public Connection getConnection() throws Exception {
    ctx = new InitialContext();
    ds1 = (javax.sql.DataSource) ctx.lookup(strDSName1);
    return ds1.getConnection();
}

您要求连接池检索这些可用连接之一。连接池会给你一个数据库连接(如果有的话),让你想用多久就用多久。然后你可以在任何你想要/需要的地方使用它并关闭它

public void foo() throws Exception {
    Connection connection = getConnection();
    //do what you want/need...

    //in the end, you close the connection
    //this is A MUST!
    connection.close();
}

从连接池检索到的连接执行connection.close() 时,您不会关闭物理数据库连接,而是通知连接池此特定数据库连接必须返回SLEEPING 状态。


解释中的一些建议:

  • 不得尝试保持连接处于活动状态,这是连接池的工作。
  • 不得尝试将连接存储在任何类似 缓存 的结构中,这是连接池的工作。
  • 必须在您需要的最短范围内检索java.sql.Connection。使用后,关闭它。

【讨论】:

  • 感谢您的快速回复。如果我理解正确,这意味着数据库会话变量仅分配给拥有我正在连接的架构的用户。如果是这种情况,那么我如何为池中的每个连接分配一个数据库 SID(因为这是我认为数据库管理员需要的)?
  • @sebster 是的,数据库会话变量将属于您在数据源中配置的用户。看起来您想为每个登录用户处理不同的连接凭据,对吧?
  • 是的,这就是我从数据库管理员那里了解到的。为什么他想要那个,不知道。他想要的听起来像是某种会话跟踪,但在数据库方面。我试图告诉他我可以在服务器端实现会话跟踪机制,但讨论以他坚持他需要这个而告终。有没有办法实现它或者这是一个荒谬的要求?
  • @sebster 请阅读stackoverflow.com/q/6500452/1065197。如果您的 DBA 真的坚持要您尝试实施类似的东西,那么您应该与项目管理员或软件架构师或有足够权力向他展示权衡取舍(特别是高成本) 实现这样的事情,特别是性能问题,通过手动打开关闭 servlet doGetdoPost 中的数据库连接并在该 servlet 上执行 1000 个(此指标可能不同)请求,很容易测试
  • Gracias Luiggi!...您帮助我阐明了这一点。我将与项目经理交谈,看看我们如何“管理” DBA。干杯!
【解决方案2】:

您的 DBA 基本上要求您通过使数据库连接等效于用户会话来避免连接池。

因此,一种选择是不使用连接池,而是使用您自己的功能来打开/关闭用户会话周围的数据库连接。不过,这看起来既复杂又不寻常。

另一种选择是检查 DBA 的要求。 DBA 可能不得不适应他需要以不同的方式跟踪状态的想法,例如通过使用与会话相关的键将他需要的状态存储在表中,而不是将状态存储在连接层中。

一般而言,在某些组件的会话处理中存储状态会增加间接复杂性,因为您开始必须关心组件如何处理过期和唯一性,因为您在这里发现 HTTP 会话状态与数据库会话的处理方式不同.

【讨论】:

  • 感谢您的回答。关于打开/关闭数据库连接的功能:这应该如何与 JBoss 配置的数据源一起完成?因为使用 DriverManager 来获得连接对我来说似乎不合适。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
  • 2014-08-21
  • 1970-01-01
  • 2013-09-10
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多