java - 了解 EJB3/JPA 容器级事务和隔离级别

标签 java jpa transactions jakarta-ee ejb-3.0

考虑一下我正在使用的一些代码的简化 View :

@Stateless(...)
@Remote(...)
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public class FirstEjbType {

   @EJB(...)
   private SecondEjbType secondEjb;
   @EJB(...)
   private ThirdEjbType thirdEjb;

   public void doSomething() {
      secondEjb.doSomething();  // WRITES SOMETHING TO THE DATABASE
      thirdEjb.doSomething();  // CAN'T SEE THAT SOMETHING IN THE DATABASE!
}

我已经设置了 TransactionAttributeMANDATORY 的注释在类(class)。我理解这意味着所有方法,如 doSomething()必须在提供的事务中调用。在这种情况下,我们使用容器管理的事务。

TransactionAttributeSecondEjbType 中根本没有使用或 ThirdEjbType ...既不在类也不在方法级别。我理解这意味着 secondEjb.doSomething()thirdEjb.doSomething()都将在为 firstEjb.doSomething() 提供的交易中运作.

但是,我严重错过了一些东西!如代码注释所示... secondEjb将数据写入数据库,thirdEjb读取该数据作为其操作的一部分。由于所有这些都在同一个事务中运行,我不认为隔离级别会有任何问题。 但是,无论出于何种原因,secondEjb数据库写入对 thirdEjb 不可见.

我一直跟踪到最大值,显然没有异常、错误或回滚问题……最初的写入对后续读取来说是不可见的。我并没有自称是世界上最伟大的交易管理大师……我是否遗漏了一些明显的东西,或者我的概念理解是否基本正确,问题可能出在其他地方?


更新 - 以下是 johnstok 要求的其他信息:

  • 我在 GlassFish 中运行
  • 我不确定您所说的“非标准刷新模式”是什么意思,所以我认为答案是否定的。
  • 我的 persistence.xml 文件如下所示:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="pu" transaction-type="JTA">
<jta-data-source>jdbc/datasource</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="toplink.cache.shared.default" value="false"/>
</properties>
</persistence-unit>
</persistence>

最佳答案

首先要检查的是 bean 2 和 3 使用 @PersistenceContext EntityManager 来获取 EntityManager 而不是 @PersistenceUnit EntityManagerFactory 后跟一个createEntityManager() 调用。

其次,检查 DataSource 是否实际设置为参与 JTA 事务(autoCommit 或相关属性应该关闭)。

最后,检查传播的一种快速但粗略的方法是调用 EntityManager.getDelegate() 方法并检查生成的对象在整个预期事务中是否相同范围。

下面是幕后工作原理.... EntityManager 在创建 bean 时注入(inject)到它是一个假的,一个简单的外观。当您尝试在事务中使用 EntityManager 引用时,容器实际上会在当前事务中挖掘,找到隐藏在事务范围内的真实 EntityManager 并将您的调用委托(delegate)给那个 EntityManager(如果事务中没有 EntityManager,容器将创建一个并添加它)。此真实 对象将是getDelegate() 的值。如果 getDelegate() 的值在 secondEjb.doSomething()thirdEjb.doSomething() 中不相同 (==) 那么您没有获得预期的传播,并且每个人都在与不同的持久性上下文对话。

请注意,在类上应用 MANDATORY 实际上只会影响在该类中定义的方法,而不影响在父类(super class)中定义的方法。如果您没有在父类(super class)上指定 @TransactionAttribute,那么无论子类如何注释,这些方法都使用默认值。我只提到这一点,因为它可能会影响您对代码的理解。

关于java - 了解 EJB3/JPA 容器级事务和隔离级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4136852/

相关文章:

sql - 与 Sequelize 的事务不起作用

java - Android BSD 套接字连接

java - Junit运行子类调用父类(super class)测试用例

java - JPA:合并并持久化,捕获 ConstraintViolationException

spring - 如何在 Spring-Boot 项目中编辑 Hibernate 设置?

java - 如何让 Spring @Transactional 回滚所有未捕获的异常?

django - 如何将服务器端游标与 django 和 psycopg2 一起使用?

java.lang.NullPointerException 通过对象输出流发送消息时

java - AWS S3 - com.amazonaws.AmazonServiceException : Request ARN is invalid

java - JAXB - XML 输出中的意外元素