6.2. JDBC 数据源概述
JDBC 1.4 标准引入了 javax.sql.DataSource 接口,它充当 java.sql.Connection 对象的 工厂。通常,这些数据源绑定到 JNDI 注册表,并位于 或 servlet 等 Java EE 组件中。关键方面是这些数据源是在 应用服务器 中配置,并按名称在部署的应用程序 中引用。
以下 连接 对象有自己的 数据源 :
| 数据源 | 连接 |
|---|---|
|
|
|
|
|
|
|
|
|
以上每个 数据源 之间最重要的区别如下:
javax.sql.DataSource最重要的是一个类似于java.sql.Connection实例的 工厂。大多数javax.sql.DataSource实现通常执行 连接池 不应更改图片的事实。这是应用程序代码应使用的唯一接口。您正在实施以下哪些方法无关紧要:- 直接 JDBC 访问
-
JPA 持久性单元配置(<
jta-data-source> 或 <non-jta-data-source>) - 常见库,如 Apache Camel 或 Spring Framework
javax.sql.ConnectionPoolDataSource最重要的是通用(特定于数据库)连接池/数据源之间的 桥接。它可以被视为 SPI 接口。应用程序代码通常处理从 JNDI 获取的通用javax.sql.DataSource对象,并由应用服务器实施(可能使用commons-dbcp2等库)。在另一个结束时,应用程序代码没有直接与javax.sql.ConnectionPoolDataSource的接口。它用于应用服务器和特定于数据库的驱动程序。以下序列图显示了这一点:
javax.sql.XADataSource是一种获取javax.sql.XAConnection和javax.transaction.xAResource的方法。与javax.sql.ConnectionPoolDataSource相同,它在应用服务器和特定于数据库的驱动程序之间使用。以下是带有不同执行器的稍有修改的图表,其中包括 JTA 事务管理器:
如上图中所示,您与 App Server 交互,这是可在其中配置 javax.sql.DataSource 和 javax.transaction.UserTransaction 实例的一般实体。这些实例可以通过 JNDI 进行访问,也可以使用 CDI 或其他依赖项机制注入。
重要的一点是,即使应用使用 XA 事务和/或连接池,应用也会与 javax.sql.DataSource 进行交互,而不是其他 JDBC 数据源接口。
6.2.1. 特定于数据库及通用数据源 复制链接链接已复制到粘贴板!
JDBC 数据源实施分为两个类别:
通用
javax.sql.DataSource实现,例如:- Apache Commons DBCP(2)
- Apache Tomcat JDBC(基于 DBCP)
-
javax.sql.DataSource、javax.sql.XADataSource和javax.sql.ConnectionPoolDataSource的数据库具体实施
常见 javax.sql.DataSource 实现可能会令人困惑,无法自行创建特定于数据库的连接。即使 通用 数据源可以使用 java.sql.Driver.connect() 或 java.sql.DriverManager.getConnection(),通常最好使用特定于数据库的 javax.sql.DataSource 实现配置此 通用 数据源。
当 通用 数据源与 JTA 交互时,它 必须配置有 javax.sql.XADataSource 的数据库特定实施。
要关闭图片,通用 数据源 通常不需要 特定于数据库的 javax.sql.ConnectionPoolDataSource 来执行连接池。现有池通常处理没有标准 JDBC 接口(javax.sql.ConnectionPoolDataSource 和 javax.sql.PooledConnection)的池,而是使用自己的自定义实施。
6.2.2. 有些通用数据源 复制链接链接已复制到粘贴板!
例如,众所周知的通用数据源 Apache Commons DBCP(2).
javax.sql.XADataSource 实现
DBCP2 不包括 javax.sql.XADataSource 的任何实施,这是预期的。
javax.sql.ConnectionPoolDataSource implementations
DBCP2 确实 包括 javax.sql.ConnectionPoolDataSource 的实施:org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS。它通过调用 java.sql.DriverManager.getConnection() 创建 javax.sql.PooledConnection 对象。这个池不应该被直接使用,它应该被视为 驱动程序的适配器 :
-
不要提供自己的
javax.sql.ConnectionPoolDataSource实现 - 您需要根据 JDBC 建议用于 连接池来使用
如上图中所示,驱动程序直接提供 javax.sql.ConnectionPoolDataSource,或利用 org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS 适配器的 帮助,而 DBCP2 实施了 应用服务器 合同之一:
-
org.apache.commons.dbcp2.datasources.PerUserPoolDataSource -
org.apache.commons.dbcp2.datasources.SharedPoolDataSource
这两个池均在配置阶段获取 javax.sql.ConnectionPoolDataSource 的实例。
这是 DBCP2 中最重要的和有趣的部分:
javax.sql.DataSource 实现
要实现连接池功能,您不必遵循 JDBC 建议 以使用 javax.sql.ConnectionPoolDataSource javax.sql.PooledConnection SPI。
以下是 DBCP 2 的一般数据源列表:
-
org.apache.commons.dbcp2.BasicDataSource -
org.apache.commons.dbcp2.managed.BasicManagedDataSource -
org.apache.commons.dbcp2.PoolingDataSource -
org.apache.commons.dbcp2.managed.ManagedDataSource
这里有 两个问题 :
基本 与 池
这个 axis 决定 池配置 方面。
两种数据源都执行 java.sql.Connection 对象的 池。唯一的 区别是:
-
使用 bean 属性 配置基本的 数据源,如
maxTotal或minIdle,用于配置org.apache.commons.pool2.impl.GenericObjectPool的内部实例。 -
池 数据源配置有外部创建/配置的
org.apache.commons.pool2.ObjectPool。
受管 与非管理
这个 axis 决定 连接创建 信息以及 JTA 行为:
非管理的基本 数据源在内部使用 java.sql.Driver.
Driver.connect()创建实例。java.sql.Connection非管理的池 数据源使用传递的
org.apache.commons.pool2.ObjectPool对象来创建java.sql.Connection实例。受管池 数据源将
java.sql.Connection实例嵌套在org.apache.commons.dbcp2.managed.ManagedConnection对象,以确保 JTA 上下文中需要调用javax.transaction.Transaction.enlistResource()。但是,仍从池配置的任何org.apache.commons.pool2.ObjectPool对象获取已嵌套的实际连接。受管的基本 数据源可从配置专用
org.apache.commons.pool2.ObjectPool。相反,配置现有的、真实的、特定于数据库的javax.sql.XADataSource对象就足够了。bean 属性用于创建org.apache.commons.pool2.impl.GenericObjectPool的内部实例,后者被传递给 受管 池数据源(org.apache.commons.dbcp2.managed.ManagedDataSource)的内部实例。
DBCP2 唯一无法执行的事情是 XA 事务恢复。DBCP2 正确放入活跃 JTA 事务中的 XAResources,但不执行恢复。这应该单独完成,配置通常特定于所选交易管理器实施(如 Narayana)。
6.2.3. 要使用的模式 复制链接链接已复制到粘贴板!
推荐的模式是:
-
创建或获取带有特定 数据库 的配置(URL、凭证等)的、特定于数据库的
javax.sql.XADataSource实例,或获取可以创建连接/XA 连接的数据库。 -
创建或获取 非特定于数据库的
javax.sql.DataSource实例(内部配置了上述、特定于数据库的数据源),具有非特定于数据库的配置(连接池、事务管理器等)。 -
使用
javax.sql.DataSource获取java.sql.Connection的实例并执行 JDBC 操作。
以下是一个 规范的示例 :
在 Fuse 环境中,有很多配置选项且不需要使用 DBCP2。