【问题标题】:Need to persist container managed transaction forcefully before its scope ends需要在其范围结束之前强制持久化容器管理的事务
【发布时间】:2017-12-02 19:07:30
【问题描述】:

我正在尝试使用 entityManager.flush() 在其范围结束之前持久化容器管理的事务

bean 类被注解

@TransactionAttribute(TransactionAttributeType.REQUIRED)

通过这个链接:how we can get JPA EntityManager Flush work,我知道使用 entityManager.flush() 不会提交事务。 DBMS 现在将知道这些数据,但其他 DB 会话将无法看到它。

我还尝试创建一个带注释的新 bean 方法

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

点击此链接how to commit a transaction in EJB? 在其范围在新 bean 方法内的其他事务中调用 entityManager.flush()。但是这不起作用。

我正在寻找一种方法来强制提交事务以将其迄今为止的当前状态保留在 DB 中。

类似:

entityManager.getTransaction().commit();

这可以为 BMT 而不是 CMT。

【问题讨论】:

    标签: hibernate jpa-2.0 ejb-3.0


    【解决方案1】:

    您可以封装将数据持久化到另一个 bean 中的逻辑,并使用@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 对其进行注释。调用此方法后,持久化的数据应该可用。

    更新版本
    ContainerManagedTranaction (CMT) 示例

    @TransactionAttribute(TransactionAttributeType.REQUIRED)    
    public class OuterBean {
        @Inject
        PersistingBean bean;
    
        public void persistData() {
            Data data = loadExisitingData();
            update(data);
            update(data);
    
            bean.persistDataInOwnTransaction(data);
    
            externalCall();
        }
    }
    
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)    
    public class PersistingBean {
        @PersistenceContext
        EntityManager em;
    
        public void persistDataInOwnTransaction(Data data) {
            em.merge(data);
          }
    }
    

    BeanManagedTransaction (BMT) 示例
    见Oracles Java EE Tutorial

    @Stateless
    @TransactionManagement(TransactionManagementType.BEAN)
    public class OuterBean {
        @Resource
        EJBContext context;
        @PersistenceContext
        EntityManager em;
    
        public void persistData() {
            UserTransaction ut = context.getUserTransaction();
    
            try {
                ut.begin();
                Data data1 = loadData1();
                update(data1);
    
                Data data2 = loadData2();
                update(data2);
    
                ut.commit();
            } catch(Exception ex) {
                ut.rollBack();
            }
    
            externalCall();
        }
    }
    

    【讨论】:

    • 我们可以在 persistDataInOwnTransaction() 中持久化新数据,而不是现有数据。我的流程是这样的: step1 :- 更新相同的数据 step2:- 更新相同的数据 step3 :- 更新相同的数据 //将所有数据更改保留到这里 step4 :- 进行外部调用 在进行外部调用之前,我需要将这些数据保存在数据库中。
    • 查看我的更新版本。目前我无法对此进行测试,但merge 会将数据重新附加到实体管理器,并且应该保留更新的数据。
    • 谢谢!该解决方案适用于该数据,但我需要更新该事务中的多个不相关实体,因此我需要将整个事务作为一个整体进行持久化。有没有办法在 public void persistData() { Data data = loadExisitingData(); 中提交事务?数据 2 数据 2 = 加载现有数据();更新(数据1);更新(数据2); ... 保存在事务 externalCall() 中完成的所有内容; }
    • 我再次更新了我的帖子,展示了一个 bean 托管事务的示例。
    • 我还注意到,在保留上述数据时,会在数据库中创建两条记录。一个由 em.merge(data) 和另一个接近完成流程的范围结束。
    【解决方案2】:

    终于,我找到了问题的解决方案。

    @Stateless
    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    public class OuterBean {
    
    @EJB
    PersistingBean bean;
    @PersistenceContext
    EntityManager em;
    
    public void persistData() {
    
        em.flush();
    
        procedureCall();
    
        Data data = loadExisitingData();
        update(data);
        update(data);
    
        bean.persistDataInOwnTransaction(data,em);
    
        em.refresh(getUpdatedEntity())
    
        externalCall();
    }
    }
    
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)   
     public class PersistingBean {
    
    public void persistDataInOwnTransaction(Data data, EntityManager em) {
    em.merge(data);
      }
    }
    

    注意:我们很幸运,我们有一个对 DB 的过程调用,因为 em.flush() 首先提交了版本 1 的事务,后来在调用 em 时被覆盖.merge(data) 与递增的休眠版本 2。

    em.merge(data) -> 在单独的事务中提交数据,因此实体将在其自己的事务中使用相同的 enityManager 在 persistDataInOwnTransaction(Data data, EntityManager em) 中作为参数传递,从而覆盖之前的实体db 具有相同的 em ID。

    em.refresh(getUpdatedEntity()) -> 从数据库中刷新实例的状态,以便任何进一步的提交都可以发生在版本 3 的这个实体上,就像在我们的例子中,在 bean 类范围的末尾。

    因此最终不会在数据库中创建多条记录。每次我们尝试使用递增的休眠版本对其进行持久化时,相同的实体都会被覆盖。

    【讨论】:

      猜你喜欢
      • 2014-10-18
      • 2012-03-23
      • 2013-09-24
      • 1970-01-01
      • 2013-07-14
      • 1970-01-01
      • 2016-02-13
      • 2015-06-17
      • 1970-01-01
      相关资源
      最近更新 更多