【问题标题】:JDBC/Connectorj: Understanding connection poolingJDBC/Connectorj:了解连接池
【发布时间】:2011-09-23 22:25:13
【问题描述】:

我想我需要更好地理解连接池的概念。我正在使用 ConnectorJ 在 Java 中工作,并将我的 servlet 部署在 Apache Tomcat 服务器上。我一直在关注文档,所以我的 Tomcat context.xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="">
  <Resource auth="Container" driverClassName="com.mysql.jdbc.Driver"
        maxActive="-1" maxIdle="30"
        maxWait="10000" minEvictableIdleTimeMillis="1200000" name="jdbc/MySQLDB"
        removeAbandoned="true" removeAbandonedTimeout="1200"  timeBetweenEvictionRunsMillis="60000"
        type="javax.sql.DataSource" url="jdbc:mysql://my_host"
        username="my_username" password="my_password"
        factory="org.apache.commons.dbcp.BasicDataSourceFactory" /> 
</Context>

我使用推荐的方式从数据源获得连接:

InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");
Connection conn = null;

try {
        conn = ds.getConnection();

        // Do query etc.
        // Close connection, statement and result set if applicable
}
catch (SQLException){
    // Handle exception here
}

我的问题是:为什么我必须在 context.xml 中为我的数据源指定用户和密码。如果我错了,请纠正我,但我认为连接池的目的是重用拥有相同连接字符串的连接?

我希望能够处理多个不同的登录(假设 servlet 接收要通过 HTTP 使用的 DB 凭据),但是如果我必须为每个可能的连接定义不同的数据源,这不违背连接池的点?

【问题讨论】:

    标签: java mysql jdbc


    【解决方案1】:

    当您使用DriverManager.getConnection 直接打开与数据库的连接时,您在该调用中提供用户名和密码以登录到数据库。

    当你使用连接池时,你并不是直接自己打开连接;相反,池会为您打开并管理连接。当然,在这种情况下,池需要知道用户名和密码才能登录数据库。

    通常,在 Java Web 应用程序中,您不会为应用程序的每个用户使用不同的数据库登录凭据。对于使用 Web 应用程序的任何人,您只需要一个应用程序使用的用户名和密码。如果 Web 应用程序的不同用户具有不同的权限,您可以通过为应用程序本身设置登录系统来进行设置,但您用于应用程序的用户名和密码与您用于登录的用户名和密码不同进入数据库。

    【讨论】:

    • 好吧,这有点清楚了。但是假设我的 servlet 中没有用户登录。我不能这样做吗?:1. getConnection("jdbc:mysql://my_host?username=my_username&amp;password=my_pwd") which will create a new connection. Perform insertion in database, and close connection.2. getConnection("jdbc:mysql://my_host?username=my_username2&amp;password=my_pwd2"), which will create a second connection. Perform insertion in database, and close connection.3. getConnection("jdbc:mysql://my_host?username=my_username&amp;password=my_pwd"), which will reuse connection 1.
    • 哇,很抱歉这么乱的评论。我不知道新行没有效果:/
    • @Tigel 不,池为您管理连接;当您从池中获得一个连接时,它不会每次都打开一个新连接,而是将一个已经打开的连接返回给您。当您“关闭”连接时,它实际上并没有关闭,它只是回到池中以处理可能需要它的后续请求。通常池不会让您使用不同的用户名和密码来管理不同的连接。
    【解决方案2】:

    与数据库的连接通常由不同的用户名和密码控制,而不是用户在网站上用于身份验证的用户名和密码。通常它只有一个用户(通常是模式名称)。连接池将使用此用户名创建所需数量的数据库连接,您的应用程序将负责从 Web 用户获取传入凭据并根据存储在数据库中的凭据进行验证。

    【讨论】:

    • 我的 servlet 基本上是一个空页面,它通过 HTTP(如 XML 字符串)接收数据,并根据数据对数据库执行操作。用户不必对自己进行身份验证。只有数据库凭据的概念。但是,他们可以在发送的数据中指定用户名和密码(例如 xml 属性)来覆盖默认连接。
    【解决方案3】:

    几件事:

    1. DataSource API 确实提供了getConnection(username, password) 方法。无论出于何种原因,Tomcat 自己使用的 Apache DBCP 都没有实现该方法。如果 DBCP 不能满足您的需求,您可能需要研究替代实现。
    2. 正如其他人所说,根据请求更改数据库凭据是一个非常晦涩的用例。也许您应该重新考虑您的设计,以便您的用户身份验证与您的数据库访问分离。
    3. 更一般地说,池化是一种技术,用于重用许多足够相似的事物,它们可以被多次重用。显然,DBCP 已决定“足够相似”不包括可跨不同数据库凭据重用。我认为原则上没有对错。

    【讨论】:

      猜你喜欢
      • 2012-09-27
      • 2016-07-06
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 1970-01-01
      • 2014-07-25
      相关资源
      最近更新 更多