【问题标题】:What is difference between @Resource UserTransaction and EntityManager.getTransaction()@Resource UserTransaction 和 EntityManager.getTransaction() 有什么区别
【发布时间】:2011-01-31 19:17:04
【问题描述】:

谁能解释两者之间的区别:

@Resource
UserTransaction objUserTransaction;

EntityManager.getTransaction();

还有什么是容器管理事务?如果我想在事务中的表中插入三行,我应该如何在我的会话外观中执行此操作。

【问题讨论】:

标签: java jpa jakarta-ee jta


【解决方案1】:

EJB 是事务性组件。事务可以由应用服务器本身管理(CMT - 容器管理事务),也可以由您自己在 EJB 中手动管理(BMT - bean 管理事务)。

EJB 通过 JTA 规范支持分布式事务。分布式事务使用UserTransaction控制,有begincommitrollback等方法。

使用 CMT,应用服务器为您启动、提交和回滚事务(根据transaction annotations),您不得干预。这意味着在这种情况下您不能访问UserTransaction。但是,使用 BMT,您可以手动执行此操作,并使用 UserTransaction 自行控制事务。

现在让我们转到EntityManager。 JPA 实现既可以在应用程序服务器中使用,也可以独立使用。如果单机使用,需要自己使用EntityManage.getTransaction来划定JDBC事务。如果在应用服务器中使用,EntityManager 可以透明地与 JTA 分布式事务管理器配合使用。

大多数时候,您在 EJB 上使用带有 @Required 注释的 CMT。这意味着您不需要访问UserTransactionEntityManager.getTransaction。该应用程序。服务器启动并提交事务,但如果引发异常,也会注意回滚。这就是我为你的立面推荐的。

(还有更多微妙之处,例如PersistenceContextType 或在EntityManager.joinTransaction 的分布式事务中手动登记实体管理器,但前提是您以不同的方式使用这些技术作为默认值)。

【讨论】:

  • 你确定EntityManager#getTransaction()在应用服务器内部运行时配合JTA分布式事务?我不这么认为,我的理解是它返回一个资源本地事务,可用于在当前 JTA 事务外部持久化数据。
  • @Pascal EntityManager 与 JTA 合作,因此您根本不应该使用 EntityManager#getTransaction。根据 javadoc,EntityManager#getTransaction 如果在 JTA EntityManager 上调用,则会抛出 IllegalStateException
  • 确实,getTransaction 在 JTA EntityManager 上调用时会引发异常)。实际上,我想到的示例(来自“Pro JPA 2”)是在会话 Bean 中获取应用程序管理的资源本地 EM - 例如用于审计日志记录 - 以及一个资源本地事务,您可以在 JTA 事务之外开始/提交任意多次。但我意识到我误读了你的答案,这与你写的不同。谢谢!
  • @Pascal 对于审计,我们使用 CMT 和 REQUIRE_NEW 作为审计方法。这是 AFAIK 使用 CMT 暂停和恢复当前事务的唯一方法。
【解决方案2】:

UserTransaction 指的是 JTA 事务实体。只有在应用程序服务器中有可用的 JTA 模块时,您才能使用它:例如,如果您在 Tomcat 上使用此模块部署应用程序(默认情况下不支持 JTA),依赖此模块的代码将失败.这是 EJB 和 MDB 中使用的默认事务类型。

EntityManager.getTransaction() 检索 本地 事务实体。这有时也称为资源本地事务。

资源本地事务与 JTA 事务有很大不同:除其他外,资源本地事务特定于资源,而 JTA 事务往往特定于特定线程。

有关资源本地事务和 JTA 事务之间区别的更多信息,请在此处查看此 stackoverflow 答案:What is the difference between a JTA and a local transaction?

【讨论】:

    【解决方案3】:

    除了@Marco 的回答,它很好地说明了 JTA 和资源本地事务之间的区别。

    Container Managed Transactions [顾名思义] 由容器而不是您的应用程序管理。这是通过 EJB 层完成的,您只需要编写您的方法,容器会将方法包装在事务上下文中,因此如果您的方法的任何部分或其较低级别的调用抛出异常,事务将回滚。

    也可以使用注释进行微调。更多信息可以在这里找到https://docs.oracle.com/javaee/5/tutorial/doc/bncij.html

    请注意,这只能通过 EJB 完成,并且注入到 Web 层的实体管理器(例如 servlet 或 REST API)不会由容器管理,在这种情况下,您必须使用 @Resource UserTransaction 查找事务或EntityManager.getTransactionbegin()commit() 你自己。

    从 Java EE 6 开始,您可以在 Web 层中使用 EJB,因此您不需要过于复杂的项目布局,除非您开始希望将 EJB 公开为 Web 服务。

    【讨论】:

    • 在 EE 容器中管理的事务可通过“@Transactional”注解在 EJB 外部使用。
    • JTA 事务不一定一定是 CMT,因为 JTA 可以在应用程序服务器(或“容器”)之外与 Bitronix 和 Atomikos 等库一起使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 2014-09-21
    • 2017-07-18
    • 1970-01-01
    • 2010-10-02
    • 2011-12-12
    • 2010-09-16
    相关资源
    最近更新 更多