6.7. 使用 JDBC 连接池


本节介绍了使用 JDBC 连接池,然后演示如何使用这些连接池模块:

重要

本章介绍了数据源管理内部的详细信息。虽然提供了关于 DBCP2 连接池功能的信息,但请记住,此连接池提供正确的 JTA 编码功能,但不提供 XA 恢复功能

为确保 XA 恢复 已就位,请使用 pax-jdbc-pool-transxpax-jdbc-pool-narayana 连接池模块。

6.7.1. 使用 JDBC 连接池简介

前面的示例演示了如何注册特定于数据库的数据源 工厂。由于 数据源 本身是连接的工厂,org.osgi.service.jdbc.DataSourceFactory 可能会被视为元工厂,它应该能够生成三种类型的数据源,以及作为 bonus,一个 java.sql.Driver:

  • javax.sql.DataSource
  • javax.sql.ConnectionPoolDataSource
  • javax.sql.XADataSource

例如,pax-jdbc-mysql 注册一个 org.ops4j.pax.jdbc.mysql.impl.MysqlDataSourceFactory,它会产生:

  • 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

规范数据源示例 所示,任何池通用 数据源都要在 JTA 环境中工作,则需要一个 数据库特定 数据源来实际获取(XA)连接。

我们已有后者,我们需要实际的、通用、可靠的连接池。

规范数据源示例 演示了如何配置特定数据库数据源的通用池。pax-jdbc-pool indices 捆绑包与上述 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 数据源接口。

这个界面只是从特定于数据库且非池数据中创建池数据源。或者更精确地,它是一个 数据源工厂 (meta factory),它将特定于数据库数据源的工厂转换为池数据源的工厂。

注意

没有这样可防止应用使用 org.osgi.service.jdbc.DataSource 对象为 javax.sql.DataSource 对象配置池,该服务 已经为 javax.sql.DataSource 对象返回池。

下表显示了哪些捆绑包注册池数据源工厂。在表格中,o.o.p.j.p 的实例代表 org.ops4j.pax.jdbc.pool

捆绑包(Bundle)PooledDataSourceFactory池密钥

pax-jdbc-pool-narayana

o.o.p.j.p.narayana.impl.Dbcp(XA)PooledDataSourceFactory

narayana

pax-jdbc-pool-dbcp2

o.o.p.j.p.dbcp2.impl.Dbcp(XA)PooledDataSourceFactory

dbcp2

pax-jdbc-pool-transx

o.o.p.j.p.transx.impl.Transx(Xa)PooledDataSourceFactory

transx

以上捆绑包只安装数据源,而不是数据源本身。应用需要调用 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.PooledDataSourceFactory 实例,它们由 pax-jdbc-pool reading 捆绑包之一注册。

如果 工厂配置包含 pool 属性,则 pax-jdbc-config 捆绑包注册的最终数据源是我们的数据库特定数据,但如果 pool=dbcp2则嵌套在以下之一:

  • org.apache.commons.dbcp2.PoolingDataSource
  • org.apache.commons.dbcp2.managed.ManagedDataSource

这与 通用数据源示例 一致。除了 pool 属性和布尔值 xa 属性外,它选择非xa 或 xa 数据源,org.ops4j.datasource factory PID 可能会包含 前缀 属性:

  • pool.*
  • factory.*

其中,每个属性都使用哪个 pax-jdbc-pool suppress 捆绑包被使用。对于 DBCP2,它是:

  • pool mdadm: bean 属性的 org.apache.commons.pool2.impl.GenericObjectPoolConfig (xa 和非 xa 场景)
  • factoryadtrust: bean 属性是 org.apache.commons.dbcp2.managed.PoolableManagedConnectionFactory (xa)或 org.apache.commons.dbcp2.PoolableConnectionFactory (non-xa)

6.7.2.1. BasicDataSource 的配置属性

下表列出了 BasicDataSource 的通用配置属性。

参数默认描述

username

 

要传递给 JDBC 驱动程序的连接用户名以建立连接。

password

 

要传递给 JDBC 驱动程序的连接密码以建立连接。

url

 

要传递给 JDBC 驱动程序的连接 URL 以建立连接。

driverClassName

 

要使用的 JDBC 驱动程序的完全限定 Java 类名称。

initialSize

0

池启动时创建的初始连接数。

maxTotal

8

可以同时从这个池分配的最大活跃连接数,或者没有限制的负数。

maxIdle

8

池中可以保持闲置的最大连接数,没有额外的连接被释放,或者没有限制。

minIdle

0

池中可以保持闲置的最小连接数量,而不创建额外的连接,或零来创建任何连接。

maxWaitMillis

无限期

池将等待的最大毫秒数(当没有可用连接时),在抛出异常前返回连接的最大毫秒数,或 -1 无限期等待。

validationQuery

 

用于从这个池验证连接的 SQL 查询,然后再将它们返回到调用者。如果指定,此查询必须是一个 SQL SELECT 语句,该语句至少返回一行。如果没有指定,通过调用 isValid ()方法来验证连接。

validationQueryTimeout

没有超时

连接验证查询失败前的超时时间(以秒为单位)。如果设置为正值,则此值将通过用于执行验证查询的声明的 setQueryTimeout 方法传递给驱动程序。

testOnCreate

false

指明对象在创建后是否会被验证。如果对象无法验证,则触发对象的浏览尝试将失败。

testOnBorrow

true

指明对象是否在从池中分离前验证对象。如果对象无法验证,它将从池中丢弃,我们将尝试浏览另一个对象。

testOnReturn

false

指明对象在返回到池之前是否会被验证。

testWhileIdle

false

指明对象是否会被闲置对象驱除(若有)验证。如果对象无法验证,它将从池中丢弃。

timeBetweenEvictionRunsMillis

-1

运行空闲对象驱除器线程之间休眠的毫秒数。当非正数时,不会运行闲置对象驱除器线程。

numTestsPerEvictionRun

3

每次运行空闲对象驱除器线程期间要检查的对象数量(若有)。

minEvictableIdleTimeMillis

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

在上面的配置中,poolxa 键是 提示 (服务过滤器属性)来选择一个注册的 org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory 服务。对于 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 安装开始。

  1. 安装 JDBC 驱动程序:

    karaf@root()> install -s mvn:mysql/mysql-connector-java/5.1.34
    Bundle ID: 223
  2. 安装 jdbcpax-jdbc-mysqlpax-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)
  3. 创建 工厂配置

    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
  4. 检查 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)
  5. 使用数据源:

    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 (这是 Narayana 事务管理器的一部分)。

6.7.4. 使用 transx 连接池模块

pax-jdbc-pool-transx 捆绑包基础,它对 pax-transx-jdbc 捆绑包上的 org.ops4j.pax.jdbc.pool.common.PooledDataSourceFactory 服务实施。pax-transx-jdbc 捆绑包使用 org.ops4j.pax.transx.jdbc.ManagedDataSourceBuilder 工具创建 javax.sql.DataSource 池。这是一个 JCA (Java™ Connector Architecture)解决方案,稍后 进行介绍。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.