连接池和数据源
连接池和数据源¶
JDBC 2在附加的可选包(也称为JDBC 2.0 标准扩展)中引入了标准连接池功能。此后,核心JDBC 3 API中包含了该特性。
总览¶
JDBC API提供了用于连接池的客户端和服务器接口。客户端接口是javax.sql.DataSource
,这是通常是应用程序获取池化数据库连接的接口。服务器接口是javax.sql.ConnectionPoolDataSource
,这是大多数应用程序服务与SeaboxSQL™JDBC驱动程序连接的接口。
在应用程序服务中,通常将引用SeaboxSQL™ConnectionPoolDataSource
实现。而应用程序组件通常会请求应用服务(而非SeaboxSQL™)实现的DataSource。
对于没有应用服务的环境,SeaboxSQL™提供了两种DataSource的实现,应用程序可以直接使用它们。一种实现执行连接池,而另一种实现仅通过DataSource接口提供对数据库连接的访问,而无需任何池。同样,除非应用程序服务不支持ConnectionPoolDataSource
接口,否则不应使用这些实现。
应用程序服务ConnectionPoolDataSource
SeaboxSQL™包含一个名为com.seaboxsql.ds.SDConnectionPoolDataSource
的ConnectionPoolDataSource
实现。
JDBC要求通过JavaBean属性配置ConnectionPoolDataSource
,如表 ConnectionPoolDataSource
配置属性所示,因此每个属性都有get和set方法。
表 ConnectionPoolDataSource配置属性
属性 | 类型 | 描述 |
---|---|---|
serverName | STRING | SeaboxSQL™ 数据服务主机名 |
databaseName | STRING | SeaboxSQL™ 数据库名 |
portNumber | INT | SeaboxSQL™ 数据库侦听的TCP端口(使用0表示采用默认端口) |
user | STRING | 建立连接使用的用户名 |
password | STRING | 建立连接使用的密码 |
ssl | BOOLEAN | 使用ssl加密连接时设为'true'(默认false) |
sslfactory | STRING | 自定义javax.net.ssl.SSLSocketFactory 类名(参考“Custom SSLSocketFactory”) |
defaultAutoCommit | BOOLEAN | 连接返回给调用者是,是否启动自动提交。默认为false,禁用自动提交。 |
许多应用程序服务器使用属性-值的语法来配置这些属性,因此将属性作为文本块输入并不罕见。 如果应用程序服务器提供了一个用于输入所有属性的区域,则可能会这样列出它们:
serverName=localhost
databaseName=test
user=testuser
password=testpassword
或者,如果将分号用作分隔符而不是换行符,则它可能看起来像这样:
serverName=localhost;databaseName=test;user=testuser;password=testpassword
应用程序数据源¶
SeaboxSQL™包括DataSource的两种实现,如表11.2“ DataSource实现”所示。一个做池,另一个不做池。当客户端调用close方法时,池实现实际上并没有关闭连接,而是将连接返回到可用连接池中,供其他客户端使用。这避免了重复打开和关闭连接的任何开销,并允许大量客户端共享少量数据库连接。
这里提供的池化数据源实现并没有提供最丰富的功能属性。在池本身关闭之前,连接永远不会关闭,也没有办法缩小池。同样,不对为默认配置用户以外的其他用户请求连接进行池化。其错误处理有时无法从池中删除断开的连接。通常,不建议使用SeaboxSQL™提供的连接池。检查您的应用程序服务或查看更优秀的jakarta commons DBCP项目。
表 DataSource实现
池化 | 实现的类 |
---|---|
No | `org.seaboxsql.ds.SDSimpleDataSource |
Yes | `org.seaboxsql.ds.SDPoolingDataSource |
两种实现都使用相同的配置方案。 JDBC要求通过JavaBean属性配置数据源,如表 数据源配置属性
所示,因此每个属性都有get和set方法。
表 数据源配置属性
属性 | 类型 | 描述 |
---|---|---|
serverName | STRING | SeaboxSQL™ 数据库服务主机名 |
databaseName | STRING | SeaboxSQL™ 数据库名 |
portNumber | INT | SeaboxSQL™ 数据库侦听的TCP端口(使用0表示采用默认端口) |
user | STRING | 建立连接使用的用户名 |
password | STRING | 建立连接使用的密码 |
ssl | BOOLEAN | 使用ssl加密连接时设为'true'(默认false) |
sslfactory | STRING | 自定义javax.net.ssl.SSLSocketFactory 类名(参考[“Custom SSLSocketFactory”] |
例 数据源代码示例
展示了一个典型的使用池化DataSource的应用代码
例 数据源代码示例
在代码中初始化一个池化的DataSource的方式如下:
SDPoolingDataSource source = new SDPoolingDataSource();
source.setDataSourceName("A Data Source");
source.setServerName("localhost");
source.setDatabaseName("test");
source.setUser("testuser");
source.setPassword("testpassword");
source.setMaxConnections(10);
接下来,使用来自池的连接代码如下所示。 请注意,最终关闭连接至关重要。 否则,该池将“泄漏”连接,并最终将所有客户端锁定。
Connection conn = null;try{
conn = source.getConnection();
// use connection}catch (SQLException e){
// log error}finally{
if (con != null)
{
try { conn.close(); } catch (SQLException e) {}
}
}
Tomcat设置¶
注意
必须将SeaboxSQL 4和5中的seaboxsql.jar文件都放在$CATALINA_HOME/common/lib中。
在这两个tomcat实例中进行设置最简单方法是使用Tomcat附带的管理Web应用程序,只需将数据源添加到要在其中使用它的上下文中即可。
Tomcat 4的安装程序将以下内容放在conf/server.xml中的
<Resource name="jdbc/seabox" scope="Shareable" type="javax.sql.DataSource"/><ResourceParams name="jdbc/seabox">
<parameter>
<name>validationQuery</name>
<value>select version();</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:seaboxsql://localhost/davec</value>
</parameter>
<parameter>
<name>password</name>
<value>davec</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>4</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>5000</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.seaboxsql.Driver</value>
</parameter>
<parameter>
<name>username</name>
<value>davec</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>2</value>
</parameter></ResourceParams>
为Tomcat 5设置时,可以使用上述方法,除了它位于<Host> ... <DefaultContext> ...
另外,还有一个conf/Catalina/hostname/context.xml
文件。 例如,http//localhost:8080/servlet-example
的目录为$CATALINA_HOME/conf/Catalina/localhost/servlet-example.xml
文件。 在此文件内,将上述xml放在
然后,使用以下代码访问连接。
import javax.naming.*;import javax.sql.*;import java.sql.*;public class DBTest
{
String foo = "Not Connected";
int bar = -1;
public void init()
{
try
{
Context ctx = new InitialContext();
if(ctx == null )
throw new Exception("Boom - No Context");
// /jdbc/seabox is the name of the resource above
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/seabox");
if (ds != null)
{
Connection conn = ds.getConnection();
if(conn != null)
{
foo = "Got Connection "+conn.toString();
Statement stmt = conn.createStatement();
ResultSet rst = stmt.executeQuery("select id, foo, bar from testdata");
if(rst.next())
{
foo=rst.getString(2);
bar=rst.getInt(3);
}
conn.close();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public String getFoo() { return foo; }
public int getBar() { return bar;}
}
数据源和JNDI¶
所有ConnectionPoolDataSource和DataSource实现都可以存储在JNDI中。对于非池实现,每次从JNDI检索对象时都会创建一个新实例,其设置与存储的实例相同。对于池实现,只要有可用的实例就会被取回(例如,从JNDI检索池的不同JVM),否则将创建具有相同设置的新实例。
在应用程序服务环境中,通常,应用程序服务器的DataSource实例将存储在JNDI中,而不是在SeaboxSQL™ ConnectionPoolDataSource实现中。
在应用程序环境中,应用程序可以将数据源存储在JNDI中,这样就不必对所有应用组件可能用到的数据源创建应用。例 DataSource JNDI代码
示例中给出了一个例子。
例 DataSource JNDI代码示例
初始化池数据源并将其添加到JNDI的应用程序代码如下所示:
SDPoolingDataSource source = new SDPoolingDataSource();
source.setDataSourceName("A Data Source");
source.setServerName("localhost");
source.setDatabaseName("test");
source.setUser("testuser");
source.setPassword("testpassword");
source.setMaxConnections(10);
new InitialContext().rebind("DataSource", source);
从池中使用连接的代码如下:
Connection conn = null;try{
DataSource source = (DataSource)new InitialContext().lookup("DataSource");
conn = source.getConnection();
// use connection}catch (SQLException e){
// log error}catch (NamingException e){
// DataSource wasn't found in JNDI}finally{
if (con != null)
{
try { conn.close(); } catch (SQLException e) {}
}
}