6.2. JDBC 数据源概述
JDBC 1.4 标准引入了 javax.sql.DataSource
接口,它充当 java.sql.Connection
对象的 工厂。通常,此类数据源绑定到 JNDI 注册表,并位于内或注入到 servlet 或 EJB 等 Java EE 组件中。主要方面是,这些数据源是在 应用服务器 内 配置的,并根据名称在部署的应用程序 中引用。
以下 连接 对象具有自己的 数据源 :
数据源 | 连接 |
---|---|
|
|
|
|
|
|
以上每个 数据源 之间最重要的区别如下:
javax.sql.DataSource
最重要的是一个 工厂-like 对象用于获取java.sql.Connection
实例。大多数javax.sql.DataSource
实施通常执行 连接池 的事实不应更改图片。这是应当供应用程序代码使用的唯一接口。您实施以下哪个项无关紧要:- 直接 JDBC 访问
-
JPA persistence 单元配置(<
jta-data-source>
或 <non-jta-data-source>
) - 流行的库,如 Apache Camel 或 Spring Framework
javax.sql.ConnectionPoolDataSource
最重要的是一个通用(特定于数据库)连接池/数据源和特定于数据库的数据源之间的 桥接。它可能被视为 SPI 接口。应用程序代码通常处理从 JNDI 获取并由应用服务器(可能使用commons-dbcp2
等库)实现的通用javax.sql.DataSource
对象。在另一端,应用程序代码不直接与javax.sql.ConnectionPoolDataSource
的接口。它用于应用服务器和特定于数据库的驱动程序。以下序列图显示了:
javax.sql.XADataSource
是获取javax.sql.XAConnection
和javax.transaction.xa.XAResource
的方法。与javax.sql.ConnectionPoolDataSource
相同,它在应用服务器和数据库特定驱动程序之间使用。以下是不同执行器的稍修改图表,这一次包括 JTA Transaction Manager:
如上两个图所示,您与 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
这里有两个 axes:
基本 与 池
这个 axis 决定 池配置 方面。
两种类型的数据源都执行 java.sql.Connection
对象的 池。唯一的 区别是:
-
使用 bean 属性配置 基本 数据源,如
maxTotal
或minIdle
,用来配置org.apache.commons.pool2.impl.GenericObjectPool
的内部实例。 -
池 数据源配置有外部创建的/配置
org.apache.commons.pool2.ObjectPool
。
受管 与非管理
这个 axis 决定 连接创建 方面和 JTA 行为:
非管理的基本数据源通过使用 内部
java.sql.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. 要使用的模式
推荐的模式是:
-
创建或获取 特定于数据库的
javax.sql.DataSource
或javax.sql.XADataSource
实例,其中包含特定于数据库的配置(URL、凭证等),可以创建 connection/XA 连接。 -
创建或获取 特定于数据库的
javax.sql.DataSource
实例(内部配置有上述、特定于数据库的数据源),以及特定于数据库的配置(连接池、事务管理器等)。 -
使用
javax.sql.DataSource
获取java.sql.Connection
的实例并执行 JDBC 操作。
以下是 规范 示例:
// Database-specific, non-pooling, non-enlisting javax.sql.XADataSource PGXADataSource postgresql = new org.postgresql.xa.PGXADataSource(); // Database-specific configuration postgresql.setUrl("jdbc:postgresql://localhost:5432/reportdb"); postgresql.setUser("fuse"); postgresql.setPassword("fuse"); postgresql.setCurrentSchema("report"); postgresql.setConnectTimeout(5); // ... // Non database-specific, pooling, enlisting javax.sql.DataSource BasicManagedDataSource pool = new org.apache.commons.dbcp2.managed.BasicManagedDataSource(); // Delegate to database-specific XADatasource pool.setXaDataSourceInstance(postgresql); // Delegate to JTA transaction manager pool.setTransactionManager(transactionManager); // Non database-specific configuration pool.setMinIdle(3); pool.setMaxTotal(10); pool.setValidationQuery("select schema_name, schema_owner from information_schema.schemata"); // ... // JDBC code: javax.sql.DataSource applicationDataSource = pool; try (Connection c = applicationDataSource.getConnection()) { try (Statement st = c.createStatement()) { try (ResultSet rs = st.executeQuery("select ...")) { // ....
在 Fuse 环境中,有许多配置选项,且不需要使用 DBCP2。