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