6.2. JDBC 数据源概述


JDBC 1.4 标准引入了 javax.sql.DataSource 接口,它充当 java.sql.Connection 对象的 工厂。通常,此类数据源绑定到 JNDI 注册表,并位于内或注入到 servlet 或 EJB 等 Java EE 组件中。主要方面是,这些数据源是在 应用服务器配置的,并根据名称在部署的应用程序 中引用

以下 连接 对象具有自己的 数据源

数据源连接

javax.sql.DataSource

java.sql.Connection

javax.sql.ConnectionPoolDataSource

javax.sql.PooledConnection

javax.sql.XADataSource

javax.sql.XAConnection

以上每个 数据源 之间最重要的区别如下:

  • javax.sql.DataSource 最重要的是一个 工厂-like 对象用于获取 java.sql.Connection 实例。大多数 javax.sql.DataSource 实施通常执行 连接池 的事实不应更改图片。这是应当供应用程序代码使用的唯一接口。您实施以下哪个项无关紧要:

    • 直接 JDBC 访问
    • JPA persistence 单元配置(< jta-data-source> 或 & lt;non-jta-data-source>)
    • 流行的库,如 Apache Camel 或 Spring Framework
  • javax.sql.ConnectionPoolDataSource 最重要的是一个通用(特定于数据库)连接池/数据源和特定于数据库的数据源之间的 桥接。它可能被视为 SPI 接口。应用程序代码通常处理从 JNDI 获取并由应用服务器(可能使用 commons-dbcp2等库)实现的通用 javax.sql.DataSource 对象。在另一端,应用程序代码不直接与 javax.sql.ConnectionPoolDataSource 的接口。它用于应用服务器和特定于数据库的驱动程序。以下序列图显示了:

    diag 7f73f899365cf56b8aa906191213fa81
  • javax.sql.XADataSource 是获取 javax.sql.XAConnectionjavax.transaction.xa.XAResource 的方法。与 javax.sql.ConnectionPoolDataSource 相同,它在应用服务器和数据库特定驱动程序之间使用。以下是不同执行器的稍修改图表,这一次包括 JTA Transaction Manager:

    diag ebfce784cac352c984238fe0a82ca4fa

如上两个图所示,您与 App Server 交互,它是一个通用的实体,您可以在其中配置 javax.sql.DataSourcejavax.transaction.UserTransaction 实例。此类实例可以通过 JNDI 访问,也可以使用 CDI 或其他依赖项机制注入。

重要

重要点是,即使应用使用 XA 事务和/或连接池,应用与 javax.sql.DataSource 交互,而不是另外两个 JDBC 数据源接口。

6.2.1. 特定于数据库和通用数据源

JDBC 数据源实现分为两个类别:

  • 通用 javax.sql.DataSource 实现,例如:

  • 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.ConnectionPoolDataSourcejavax.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 属性配置 基本 数据源,如 maxTotalminIdle,用来配置 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.DataSourcejavax.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。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.