为什么使用DataSource而不是XADataSource?

12
据我了解,DataSource 连接有两种类型,分别是 javax.sql.DataSourcejavax.sql.XADataSource这个教程 解释说,javax.sql.DataSource 使连接能够池化,而 javax.sql.XADataSource 则提供连接的分布式事务行为。

我了解大多数 XADataSource 都会实现连接池和分布式事务,因此我认为使用 XADataSource 可以同时具备两者功能,而不必使用 DataSource
在选择 XADataSource 还是 DataSource 时,是否存在任何权衡之处?
我了解到,XADataSource 不一定要使用池化连接,是否有一种方法可以找出一个 XADataSource 是否使用池化连接?还是只能依靠 XADataSource 提供者的文档?
编辑:
我提到 javax.sql.DataSourcejavax.sql.XADataSource 是因为它们是 Tomcat 8 工厂提供的类型

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

根据类型创建 org.apache.tomcat.jdbc.pool.DataSource 或 org.apache.tomcat.jdbc.pool.XADataSource。

我确实了解到,在我的代码中,作为 API,最终会使用 DataSource 来抽象底层实现... 我的问题更多地涉及到当我配置 Tomcat 8(或任何其他服务器)时必须经过的决策过程。

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


XADataSource 用于 two-phase 提交以同步不同应用程序实例使用的数据。我只记得在使用 Oracle ATG Commerce 时有这个区别,它使用 JTDataSource,底层使用 XADataSource - harshavmb
1个回答

11

何时配置XADataSource

如第二节所述,您的代码将始终使用DataSource接口(可能使用XADataSource)。如果问题是何时应使用XADataSource(例如在应用程序服务器中配置它),则答案很简单:

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

如果您不需要分布式事务,那么仍然可以配置XADataSource,但这可能会产生一些开销,例如未使用的额外对象(例如XAResource)以及数据源执行的“簿记”方面。不过,这种开销可能是可以忽略不计的。

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

  1. 不需要分布式事务:

    程序--使用--> Tomcat连接池DataSource--使用--> JDBC驱动程序DataSource

  2. 需要分布式事务:

    程序--使用--> Tomcat连接池DataSource--使用--> JDBC驱动程序XADataSource

在两种情况下,连接池都由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的实现。
  • JDBC驱动程序,它们实现 XADataSourceXAConnectionXAResource接口。这些在下一节中描述。
  • 应用程序可见的DataSource实现,以“覆盖”每个XADataSource对象,并与事务管理器交互。该DataSource实现通常由应用服务器提供。
  • 资源管理器(s)来管理底层数据。在JDBC API的上下文中,资源管理器是一个DBMS服务器。术语“资源管理器”是从JTA借来的,以强调使用JDBC API进行分布式事务遵循该文档中指定的架构。
简而言之:你--使用-->DataSource--(可能)使用-->XADataSource
另外注意:在各种JDBC实现中,历史上存在着有关职责的某些混淆,在某些情况下,连接池同时实现了所有三个接口。

我不确定“作为连接的用户”是这里最有帮助的观点...我觉得问题的精神更像是“为什么要定义DataSource而不是在每个方面都似乎更优越的XADataSource”。 - Deltharis
@Deltharis 啊,我明白你的意思。让我看看我能否解决这个问题。 - Mark Rotteveel
我的问题实际上就是@Deltharis所说的...我会稍微澄清一下。 - Michel Feinstein
@MarkRotteveel 我的假设并不是他们会这样做,而是他们可能会这样做(实际上我认为大多数人都会这样做),我是基于这个文档:http://docs.oracle.com/javase/tutorial/jdbc/basics/sqldatasources.html#deployment_distributed_transactions 来做出自己的判断的。当它说“在这种情况下,类com.applogic.TransactionalDS被实现为生成连接也是池化连接,这通常是作为EJB服务器实现的一部分提供的DataSource类的情况。” - Michel Feinstein
@mFeinstein 不是的,我从来没有这么说过。通常使用 XADataSource 的数据源也会提供连接池;Tomcat 就是这样做的。再次强调,这是由于混淆了 JDBC 术语:javax.sql.ConnectionPoolDataSource 不是连接池(在某些方面,javax.sql.XADataSourceConnectionPoolDataSource 的一种特殊形式,只是它没有扩展该接口)。两者都可以被 DataSource 实现所使用,以提供连接池和/或分布式事务。 - Mark Rotteveel
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接