为啥使用 DataSource 而不是 XADataSource?

Posted

技术标签:

【中文标题】为啥使用 DataSource 而不是 XADataSource?【英文标题】:Why use DataSource instead of XADataSource?为什么使用 DataSource 而不是 XADataSource? 【发布时间】:2017-10-27 00:31:54 【问题描述】:

据我了解DataSource 连接有两种类型,javax.sql.DataSourcejavax.sql.XADataSource,this tutorial 解释说javax.sql.DataSource 赋予连接池化的能力,javax.sql.XADataSource 赋予连接分布式交易行为。

我知道大多数XADataSource 将实现连接池以及分布式事务,因此当您可以使用XADataSource 并同时使用两者时,我认为使用DataSource 没有意义。

在选择XADataSource 而不是DataSource 时是否有任何权衡?

我知道XADataSource 使用池连接不是强制性的,有没有办法查明XADataSource 是使用池连接还是仅依赖XADataSource 提供者的文档?


编辑:

我指的是javax.sql.DataSourcejavax.sql.XADataSource,因为它们是types Tomcat 8 factory gives you:

类型应始终为 javax.sql.DataSourcejavax.sql.XADataSource

取决于类型 org.apache.tomcat.jdbc.pool.DataSource 或 org.apache.tomcat.jdbc.pool.XADataSource 将被创建。

我明白最后我会在我的代码上使用DataSource 作为 API,抽象底层实现......我的问题与我必须经历的决策过程有关配置Tomcat 8(或任何其他服务器)。

我想要池连接,并且有许多XADataSource 实现可以提供事务连接和池连接,那么如果我能获得更多,为什么不总是使用XADataSource? (这当然不适用于不实现池连接的XADataSource

【问题讨论】:

XADataSource 用于two-phase 提交以同步不同应用程序实例使用的数据。我只记得在处理 Oracle ATG Commerce 时的这种差异,它使用 JTDataSource 在引擎盖下有 XADataSource 【参考方案1】:

何时配置XADataSource

如第二部分所述,您的代码将始终使用DataSource 接口(可能使用XADataSource)。如果问题是你应该什么时候使用XADataSource(例如在你的应用服务器中配置它),那么答案很简单:

如果您需要分布式事务,请使用XADataSource:即确保事务跨多个资源(例如不同的数据库)成功或失败。

如果您不需要分布式事务,那么您仍然可以配置XADataSource,但这可能会在内存和处理方面产生一些开销,例如未使用的额外对象(例如XAResource),以及也许就数据源所做的“簿记”而言。不过,这种开销可能可以忽略不计。

一些数据源(例如您的问题中提到的 Tomcat 池),可以使用 DataSourceXADataSource 作为工厂来创建连接(根据 JDBC 规范,ConnectionPoolDataSource 也应该可用作为工厂,但看起来 Tomcat 忽略了该选项)。这不会改变您决定使用什么的方式:

    不需要分布式事务:

    程序 --uses--> Tomcat连接池DataSource --uses--> JDBC驱动@​​987654332@

    需要分布式事务:

    程序--uses--> Tomcat连接池DataSource --uses--> JDBC驱动@​​987654334@

在这两种情况下,连接池都由 Tomcat 连接池 DataSource 提供,而不是由 JDBC 驱动程序 (XA)DataSource 提供。 XADataSource 的正确* 实现不会实现连接池:这将是使用XADataSource 作为其工厂的DataSource 实现的(可选)责任。所以这不是选择(或不选择)XADataSource 的理由。

您的问题可能源于 XADataSource 创建扩展 PooledConnectionXAConnection 的令人困惑的术语。 PooledConnection 这个名字并不意味着它来自一个连接池,它意味着在创建之后这些 可以 被保存在一个连接池中(这将在名为 XADataSource.getXAConnectionDataSource 内)。

DataSourceXADataSource 的职责

在 JDBC 中,DataSource 的职责是创建应用程序可以使用的连接。这意味着它可以是一个非常基本的实现,只是直接转到DriverManager,但它也是一个提供连接池和支持分布式事务的实现。

这个想法是您可以将一种实现换成另一种,而您的代码不会受到影响。

因此,使用代码的连接应始终使用javax.sql.DataSource 实现。 javax.sql.XADataSource(以及javax.sql.ConnectionPoolDataSource)旨在供javax.sql.DataSource 实现使用,这些实现提供了连接池和/或分布式事务等高级功能。它们不应该直接在您自己的程序中使用。正如您链接的教程所说:

同样,当DataSource 实现被实现为与XADataSource 类一起使用时,它产生的所有连接都将自动成为可用于分布式事务的连接。

换句话说,DataSource 是您用来获取连接的 API,而 XADataSource 由提供分布式事务支持的数据源库使用。它获取XAConnection,将其注册到分布式事务管理器,然后为您提供从XAConnection.getConnection() 获取的逻辑连接。

这也是 JDBC 4.2 规范第 12.1 节中的描述:

分布式事务需要提供这些的基础设施 角色:

事务管理器 — 控制事务边界并管理两阶段提交协议。这通常是一个 JTA 的实施。 实现XADataSourceXAConnectionXAResource 接口的JDBC 驱动程序。这些将在下一节中介绍。 DataSource 的应用程序可见实现“坐在”每个XADataSource 对象之上并与事务交互 经理。 DataSource 实现通常由 应用服务器。 用于管理基础数据的资源管理器。在 JDBC API 的上下文中,资源管理器是一个 DBMS 服务器。术语 “资源管理器”是从 JTA 中借用的,以强调这一点 使用 JDBC API 的分布式事务遵循架构 在该文件中指定。

TL;DR: 你 -- 使用 --> DataSource --(可能)使用 --> XADataSource


*:历史上,各种 JDBC 实现在职责方面存在一些混淆,在某些情况下,连接池同时实现了所有三个接口。

【讨论】:

我不确定“作为连接的用户”是这里最有用的观点......我觉得问题的精神更像是“为什么定义 DataSource 而不是 XADataSource似乎各方面都优越” @Deltharis 我添加了一个不同的介绍,但重点是:DataSource 是连接“用户”的接口。 XADataSource 只是对你隐藏的管道。 是的,但是,我在实现之间进行选择的唯一工作流是在应用程序服务器中定义数据源时。在实现应用程序本身时,我从来不需要这些知识,因为技术堆栈的某些部分本身处理了连接(并且可能总是在您编写时使用DataSource)。在我看来,对这个问题的回答应该解决定义方面,而不是“连接用户”方面。 @Deltharis 啊,我明白你的意思了。让我看看我是否也能解决这个问题。 我的问题确实是@Deltharis 所说的......我会澄清一下。

以上是关于为啥使用 DataSource 而不是 XADataSource?的主要内容,如果未能解决你的问题,请参考以下文章

为啥设置 DataSource 时 ComboBox 不抛出异常?

为啥 DataSource 不能在 Spring Boot 应用程序中自动装配?

为啥我总是要使用 ||而不是 |和 && 而不是 &?

为啥使用常量而不是枚举?

为啥 Kivy 使用浮点数而不是整数?

为啥使用 var 而不是类名? [复制]