这是很多问题:) 我将尝试完成以前的答案。
Is there a better way to simulate the DB failure?
测试所有情况很复杂。测试主要案例的一种方法是创建一个 JCA 连接器(数据库驱动程序是一个 JCA 连接器)。您可以从将在事务中登记的连接器(第三个参与者)获取连接。然后连接可能会引发某些错误。
三个部分协同工作:(1) 应用程序,(2) 应用程序。服务器的事务管理器,以及 (3) jca 连接器(所谓的资源适配器)。
连接通过 将自身挂钩到事务中ManagedConnection.getXAResource
。使用自定义 jca 连接器,您可以向应用程序(Connection
在图片中)或应用程序服务器的事务管理器(XAResource
通过ManagedConnection
图片中获得)引发异常。XAResource.prepare
您可以在和期间抛出异常XAResource.commit
,这对应于2 阶段提交 期间的错误。
请注意,很难控制参与者的入伍顺序(请参阅此问题)。所以很容易测试其中一个prepare
失败(即你的失败),但很难控制它们被调用的顺序。重现 2 阶段提交的所有可能的无效状态是复杂的,尤其是在进行优化时。
(我曾经写过一个 JCA 连接器(http://code.google.com/p/txfs),如果你想要示例代码,周围还有其他的。)
What happens to the connection object when DB connection goes bad?
Does it retain its value or does it become null?
ManagedConnection
可以通知事务管理器。其中一个通知是ConnectionEvent.CONNECTION_ERROR_OCCURRED
通知它在使用此特定连接时发生错误。
如其他答案所述,通常每个事务关联一个托管连接。托管连接抽象了物理连接,你不想用太多。该应用程序仅获得“句柄”(Connection
在图片中)。在一个给定事务中获得的句柄都指向同一个托管连接。这是大多数应用服务器支持的优化。
如果托管连接无效,则使用它的句柄也会无效。但是手柄不能“刷新”AFAIK。事务必须回滚,托管连接被破坏。当另一个事务启动时,它将与池中的另一个有效托管连接相关联。
What actually happens when application tries to reconnect to DB?
What value does connection object get?
Does it use an existing value from the connection pool?
应用服务器管理一个托管连接池。如上一段所述,使用时可能会变坏。但是一个人也可能在没有被使用的情况下变坏。例如,池中已使用的托管连接可能会因为底层物理连接超时而变得无效。应用服务器通常具有在开始使用托管连接之前测试托管连接是否有效的功能。如果不是,它将尝试从池中创建另一个托管连接,或者创建一个新连接。