6.7. 使用 JDBC 连接池
本节提供使用 JDBC 连接池的介绍,然后显示如何使用这些连接池模块:
本章介绍数据源管理内部的信息。虽然提供了 DBCP2 连接池功能的信息,但请记住,这个连接池提供正确的 JTA enlist 功能,但不提供 XA 恢复。
为确保 XA 恢复 就位,使用 pax-jdbc-pool-transx
或 pax-jdbc-pool-narayana
连接池模块。
6.7.1. 使用 JDBC 连接池简介
前面的示例显示了如何注册特定于数据库的数据源 工厂。由于 数据源 本身是连接的工厂,因此 org.osgi.service.jdbc.DataSource
onnectionFactoryy 可以被视为一个 元数据工厂,应能够生成三种类型的数据源,再加上一种好处,它是 java.sql.Driver
):
-
javax.sql.DataSource
-
javax.sql.ConnectionPoolDataSource
-
javax.sql.XADataSource
例如,pax-jdbc-mysql
注册一个 org.ops4j.pax.jdbc.mysql.impl.MysqlDataSource
factory,它将生成:
-
javax.sql.DataSource
com.mysql.jdbc.jdbc2.optional.MysqlDataSource
-
javax.sql.ConnectionPoolDataSource
com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
-
javax.sql.XADataSource
com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
-
java.sql.Driver
com.mysql.jdbc.Driver
PostgreSQL 驱动程序本身实施 OSGi JDBC 服务并生成:
-
javax.sql.DataSource
org.postgresql.jdbc2.optional.PoolingDataSource
(如果指定了池相关的属性)或org.postgresql.jdbc2.optional.SimpleDataSource
-
javax.sql.ConnectionPoolDataSource
org.postgresql.jdbc2.optional.ConnectionPool
-
javax.sql.XADataSource
org.postgresql.xa.PGXADataSource
-
java.sql.Driver
org.postgresql.Driver
如 规范 DataSource 示例 所示,任何 池、通用 数据源(如果希望在 JTA 环境中工作)都需要一个 数据库特定的 数据源来实际获取(XA)连接。
我们已拥有后者,我们需要实际的通用、可靠的连接池。
规范 DataSource 示例 显示如何使用特定数据库数据源配置通用池。pax-jdbc-pool-*
捆绑包与上述 org.osgi.service.jdbc.DataSourceFactory
服务一起工作。
正如 OSGI Enterprise R6 JDBC 规范提供 org.osgi.service.jdbc.DataSourceFactory
标准接口,pax-jdbc-pool-common
提供 专有 org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory
接口:
public interface PooledDataSourceFactory { javax.sql.DataSource create(org.osgi.service.jdbc.DataSourceFactory dsf, Properties config) }
这个界面完全符合这个重要备注,前文中会值得重复操作:
即使应用使用 XA 事务和/或连接池,应用程序也会与 javax.sql.DataSource
进行交互,而不是两个其他 JDBC 数据源接口。
这个接口只是从特定数据库(非后台数据)创建一个池化数据源。或者更精确地说,它是一个数据源工厂 (元数据工厂),将特定于数据库的数据源的工厂转变为池化数据源的因素。
使用 org.osgi.service.jdbc.DataSources.jdbc.DataSourcey 服务可以防止应用程序为
Source 对象配置池,因此无法为 javax.sql.DataSource
Sourcejavax.sql.DataSource
对象返回池。
下表显示了哪些捆绑包注册了池化数据源因素。在表格中,o.o.p.j.p
的实例代表 org.ops4j.pax.jdbc.pool
。
捆绑包(Bundle) | PooledDataSourceFactory | 池密钥 |
---|---|---|
|
|
|
|
|
|
|
|
|
以上捆绑包只安装数据源因子,而不是数据源本身。应用程序需要调用 javax.sql.DataSource create(org.osgi.service.jdbc.DataSourceFactory dsf, Properties config)
方法的内容。
6.7.2. 使用 dbcp2
连接池模块
关于通用数据源的小节 提供了有关如何使用和配置 Apache Commons DBCP 模块的示例。本节演示了如何在 Fuse OSGi 环境中进行此操作。
考虑 第 6.4.1 节 “PAX- JDBC 配置服务” 捆绑包。除了跟踪以下内容外:
-
org.osgi.service.jdbc.DataSourceFactory
services -
org.ops4j.datasource
factory PIDs
该捆绑包还跟踪 org.ops4j.pax.jdbc.pool.common.PooledDataSource elementy
的实例,这些实例由 pax-jdbc-pool-*
捆绑包之一注册。
如果 factory 配置中包含 pool
属性,则 pax-jdbc-config
捆绑包注册的最终数据源是特定于数据库的数据,但是如果 pool=dbcp2
之一嵌套在以下之一中:
-
org.apache.commons.dbcp2.PoolingDataSource
-
org.apache.commons.dbcp2.managed.ManagedDataSource
这与 通用数据源示例 一致。除 pool
属性外,以及 boolean xa
属性(选择非 xa 或 xa 数据源外,org.ops4j.datasource
factory PID 可以包含 前缀 属性:
-
pool.*
-
factory.*
使用每个属性的位置取决于使用哪个 pax-jdbc-pool-*
捆绑包。对于 DBCP2,它是:
-
pool.*
: bean 属性org.apache.commons.pool2.impl.GenericObjectPoolConfig
(xa 和 non-xa 情境) -
factory.*
:org.apache.commons.dbcp2.managed.PoolableManagedConnectionFactory
(xa)或org.apache.commons.dbcp2.PoolableConnectionFactory
(non-xa)的属性
6.7.2.1. BasicDataSource 的配置属性
下表列出了 BasicDataSource 的通用配置属性。
参数 | 默认 | 描述 |
---|---|---|
| 要传递给 JDBC 驱动程序的连接用户名,以建立连接。 | |
| 要传递给 JDBC 驱动程序的连接密码,以建立连接。 | |
| 要传递给 JDBC 驱动程序的连接 URL 来建立连接。 | |
| 要使用的 JDBC 驱动程序的完全限定 Java 类名称。 | |
| 0 | 池启动时创建的初始连接数。 |
| 8 | 可同时从这个池中分配的最大活跃连接数,或对没有限制的负数。 |
| 8 | 池中可以保持闲置的最大连接数,没有释放的额外连接数,或对没有限制的负数。 |
| 0 | 池中可以保持闲置的最少连接数,如果没有创建额外数量,或零可用于创建 none。 |
| 无限期 | 在引发异常前,池要等待的最大毫秒数(当没有可用的连接时),然后再放弃异常或 -1 以无限期地等待连接。 |
| 在将连接返回给调用者之前,将用于验证来自这个池的连接的 SQL 查询。如果指定,此查询 MUST 是返回至少一个行的 SQL SELECT 语句。如果没有指定,则连接将通过调用 isValid()方法进行验证。 | |
| 没有超时 | 连接验证查询失败前的超时时间(以秒为单位)。如果设置为正值,则该值将通过执行验证查询的声明的 setQueryTimeout 方法传递到驱动程序。 |
| false | 创建后验证对象是否会被验证。如果对象无法验证,则触发对象的创建尝试将失败。 |
| true | 在从池中分离前验证对象是否会被验证。如果对象无法验证,它将从池中丢弃,我们将尝试再浏览。 |
| false | 表示在返回到池之前验证对象是否会被验证。 |
| false | 表明对象是否由空闲对象驱除器(若有)验证。如果对象无法验证,它将从池中丢弃。 |
| -1 | 空闲对象驱除器线程之间休眠的毫秒数。当非正向时,将不会运行闲置对象驱除或线程。 |
| 3 | 每次运行闲置对象驱除器线程时要检查的对象数量(若有)。 |
| 1000 * 60 * 30 | 对象在有空闲对象驱除或满足驱除前可能会处于空闲状态的最小时间(若有)。 |
6.7.2.2. 如何配置 DBCP2 池示例
以下是一个现实示例(如使用 SSL=false
)配置 DBCP2 池(org.ops4j.datasource-mysql
factory PID),它使用带有 jdbc.
-prefixed 属性的便捷语法:
# Configuration for pax-jdbc-config to choose and configure specific org.osgi.service.jdbc.DataSourceFactory dataSourceName = mysqlds dataSourceType = DataSource osgi.jdbc.driver.name = mysql jdbc.url = jdbc:mysql://localhost:3306/reportdb jdbc.user = fuse jdbc.password = fuse jdbc.useSSL = false # Hints for pax-jdbc-config to use org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory pool = dbcp2 xa = false # dbcp2 specific configuration of org.apache.commons.pool2.impl.GenericObjectPoolConfig pool.minIdle = 10 pool.maxTotal = 100 pool.initialSize = 8 pool.blockWhenExhausted = true pool.maxWaitMillis = 2000 pool.testOnBorrow = true pool.testWhileIdle = false pool.timeBetweenEvictionRunsMillis = 120000 pool.evictionPolicyClassName = org.apache.commons.pool2.impl.DefaultEvictionPolicy # dbcp2 specific configuration of org.apache.commons.dbcp2.PoolableConnectionFactory factory.maxConnLifetimeMillis = 30000 factory.validationQuery = select schema_name from information_schema.schemata factory.validationQueryTimeout = 2
在上述配置中,池和
xa
键是 提示 (服务过滤器属性)用于选择一个注册的 org.ops4j.pax.jdbc.pool.common.PooledDataSource factorsy
服务。对于 DBCP2,这是:
karaf@root()> feature:install pax-jdbc-pool-dbcp2 karaf@root()> bundle:services -p org.ops4j.pax.jdbc.pool.dbcp2 OPS4J Pax JDBC Pooling DBCP2 (230) provides: -------------------------------------------- objectClass = [org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory] pool = dbcp2 service.bundleid = 230 service.id = 337 service.scope = singleton xa = false ----- objectClass = [org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory] pool = dbcp2 service.bundleid = 230 service.id = 338 service.scope = singleton xa = true
为了完整性,以下是添加至 上一示例 中的连接池配置的完整示例。这假设您正在从全新的 Fuse 安装开始。
安装 JDBC 驱动程序:
karaf@root()> install -s mvn:mysql/mysql-connector-java/5.1.34 Bundle ID: 223
安装
jdbc
、pax-jdbc-mysql
和pax-jdbc-pool-dbcp2
功能:karaf@root()> feature:repo-add mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.3.0/xml/features-gpl Adding feature url mvn:org.ops4j.pax.jdbc/pax-jdbc-features/1.3.0/xml/features-gpl karaf@root()> feature:install jdbc pax-jdbc-mysql pax-jdbc-pool-dbcp2 karaf@root()> service:list org.osgi.service.jdbc.DataSourceFactory ... [org.osgi.service.jdbc.DataSourceFactory] ----------------------------------------- osgi.jdbc.driver.class = com.mysql.jdbc.Driver osgi.jdbc.driver.name = mysql service.bundleid = 232 service.id = 328 service.scope = singleton Provided by : OPS4J Pax JDBC MySQL Driver Adapter (232) karaf@root()> service:list org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory [org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory] -------------------------------------------------------- pool = dbcp2 service.bundleid = 233 service.id = 324 service.scope = singleton xa = false Provided by : OPS4J Pax JDBC Pooling DBCP2 (233) [org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory] -------------------------------------------------------- pool = dbcp2 service.bundleid = 233 service.id = 332 service.scope = singleton xa = true Provided by : OPS4J Pax JDBC Pooling DBCP2 (233)
创建 factory 配置 :
karaf@root()> config:edit --factory --alias mysql org.ops4j.datasource karaf@root()> config:property-set osgi.jdbc.driver.name mysql karaf@root()> config:property-set dataSourceName mysqlds karaf@root()> config:property-set dataSourceType DataSource karaf@root()> config:property-set jdbc.url jdbc:mysql://localhost:3306/reportdb karaf@root()> config:property-set jdbc.user fuse karaf@root()> config:property-set jdbc.password fuse karaf@root()> config:property-set jdbc.useSSL false karaf@root()> config:property-set pool dbcp2 karaf@root()> config:property-set xa false karaf@root()> config:property-set pool.minIdle 2 karaf@root()> config:property-set pool.maxTotal 10 karaf@root()> config:property-set pool.blockWhenExhausted true karaf@root()> config:property-set pool.maxWaitMillis 2000 karaf@root()> config:property-set pool.testOnBorrow true karaf@root()> config:property-set pool.testWhileIdle alse karaf@root()> config:property-set pool.timeBetweenEvictionRunsMillis 120000 karaf@root()> config:property-set factory.validationQuery 'select schema_name from information_schema.schemata' karaf@root()> config:property-set factory.validationQueryTimeout 2 karaf@root()> config:update
检查
pax-jdbc-config
是否处理配置到javax.sql.DataSource
服务:karaf@root()> service:list javax.sql.DataSource [javax.sql.DataSource] ---------------------- dataSourceName = mysqlds dataSourceType = DataSource factory.validationQuery = select schema_name from information_schema.schemata factory.validationQueryTimeout = 2 felix.fileinstall.filename = file:${karaf.etc}/org.ops4j.datasource-mysql.cfg jdbc.password = fuse jdbc.url = jdbc:mysql://localhost:3306/reportdb jdbc.user = fuse jdbc.useSSL = false osgi.jdbc.driver.name = mysql osgi.jndi.service.name = mysqlds pax.jdbc.managed = true pool.blockWhenExhausted = true pool.maxTotal = 10 pool.maxWaitMillis = 2000 pool.minIdle = 2 pool.testOnBorrow = true pool.testWhileIdle = alse pool.timeBetweenEvictionRunsMillis = 120000 service.bundleid = 225 service.factoryPid = org.ops4j.datasource service.id = 338 service.pid = org.ops4j.datasource.fd7aa3a1-695b-4342-b0d6-23d018a46fbb service.scope = singleton Provided by : OPS4J Pax JDBC Config (225)
使用数据源:
karaf@root()> jdbc:query mysqlds 'select * from incident' date │ summary │ name │ details │ id │ email ──────────────────────┼────────────┼────────┼───────────────────────────────┼────┼───────────────── 2018-02-20 08:00:00.0 │ Incident 1 │ User 1 │ This is a report incident 001 │ 1 │ user1@redhat.com 2018-02-20 08:10:00.0 │ Incident 2 │ User 2 │ This is a report incident 002 │ 2 │ user2@redhat.com 2018-02-20 08:20:00.0 │ Incident 3 │ User 3 │ This is a report incident 003 │ 3 │ user3@redhat.com 2018-02-20 08:30:00.0 │ Incident 4 │ User 4 │ This is a report incident 004 │ 4 │ user4@redhat.com
6.7.3. 使用 narayana
连接池模块
pax-jdbc-pool-narayna
模块几乎都是 pax-jdbc-pool-dbcp2
。它为 XA 和非 XA 场景安装 DBCP2- 特定 org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory
。唯一的 区别是,在 XA 情景中,会有一个额外的集成点。org.jboss.tm.XAResourceRecovery
OSGi 服务由 com.arjuna.ats.arjuna.recovery.recoveryManager(recovery.RecoveryManager
)进行注册,这是 Narayana 事务管理器的一部分。
6.7.4. 使用 transx
连接池模块
pax-jdbc-pool-transx
捆绑包基于其在 pax-transx-jdbc
bundle 上的 org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory
服务。pax-transx-jdbc
捆绑包通过使用 org.ops4j.pax.transx.jdbc.ManagedDataSourceBuilder
工具来创建 javax.sql.DataSource
SourceSourceSourceSources。这是 JCA(Java™ 连接器架构)解决方案,后文中 所述。