【问题标题】:How to make database update when method finish in JPAJPA中方法完成时如何更新数据库
【发布时间】:2020-06-16 10:33:56
【问题描述】:

有一个业务逻辑,首先调用一个方法来保存实体。 next 方法从数据库中获取一些数据。当调用该结果列表的第二种方法包含实体的先前值时,因为实体尚未保存。有没有办法同步这个业务逻辑,以便在第一个方法事务完成后调用第二个方法。

使用EntityManager em来持久化数据,这里是代码

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class DemoService { 

    @PersistenceContext(unitName = "primary")
    private EntityManager em;

    public  Demo createOrUpdate (Demo obj) {

      //This function is to update enity
      createOrUpdate_(obj);

      //In this function need to get updated enities(latest saved)
      fetchResultSet();
      return obj;  
    }


    @Transactional
    public  Demo createOrUpdate_ (Demo obj) {
      em.merge(obj);
      return obj;  
    }

} 



【问题讨论】:

  • 当你从同一个类中调用一个方法时,你在 createOrUpdate 上的 @Transactional 不会做任何事情。所以有两种可能的解决方案:将 createOrUpdate 移动到另一个服务或获取对 demoService 的引用并调用公共方法,以便事务拦截器完成它的工作。
  • 感谢您的回复,但是否有任何理由“当您从同一个类中调用一个方法时,您在 createOrUpdate 上的 @Transactional 不会做任何事情。”?
  • 对于带有@Transactional 注释的bean 来说,会创建一个代理对象。如果你在任何地方注入这个bean并使用它,你就是通过代理访问这个bean。代理负责事务处理。但是如果你直接从你的类中调用你的方法,你就不会通过这个代理。所以不会创建交易。也许这个帖子的答案中的链接也可以帮助你:stackoverflow.com/questions/23194777/…
  • 好的,当我从外面(从休息服务)调用我的第二种方法时,它会起作用。我注意到的是,当第一个方法返回对休息服务的响应时,DML 查询在最后执行。即使删除 @Transactional 它的行为相同。@TomStoemer
  • 由于您的整个 bean 是一个 EJB 并使用 @TransactionalAttribute 注释,所有方法也是事务性的,除非另有注释。

标签: hibernate rest jpa jta


【解决方案1】:

当您调用 fetchResultSet() 方法时,没有发生提交 - 它发生在调用方法(在您的情况下为 createOrUpdate(Demo obj))无任何异常结束时。

您也不是在 createOrUpdate_(Demo) 方法中返回合并的实体。请注意,根据 API,EntityManager#merge(T) 将它们作为托管实体作为返回对象,因此您的指针 obj 可能会链接到您的原始实体。附带说明一下,理想情况下,您不应直接在服务类中使用 entityManager。

我建议您将代码更改为这样的内容(不完整,使用 EJB 而不是 CDI,但我认为它足够显示)。首先是基地经理。

public abstract BaseManager<T> {

    @PersistenceContext
    private EntityManager em;
    
    protected abstract Class<T> getEntityClass();

    @TransactionAttribute
    public T createOrUpdate(T e) {
        if (em.contains(e)) {
            em.persist(e);
            return e;
        } else {
            return em.merge(e);
        }
    }

    public List<T> findAll() {
        String q = String.format("SELECT o FROM %s AS o", getEntityClass().toCanonicalName()0;
        return em.createQuery(q, getEntityClass()).getResultList();
    }
}

那么,实体管理器:

@Stateless
public DemoManager extends BaseManager<Demo> {

    protected Class<Demo> getEntityClass() {
        return Demo.class;
    }
}

现在,你的服务类:

@Stateless
public ExampleService {

    @EJB
    private DemoManager demoManager;

    public Set<Demo> addDemoToSet(Demo demo) {
        demoManager.createOrUpdate(demo);
        return new HashSet<>(demoManager.findAll());
    }
}

使用这种方法,对 demoManager.createOrUpdate 的调用将是事务性的,您的 findAll 后续调用将获取所有元素(如果这是您的目标)。

【讨论】:

    猜你喜欢
    • 2017-09-19
    • 2011-12-14
    • 2021-11-25
    • 2019-03-02
    • 1970-01-01
    • 2018-05-23
    • 2020-01-31
    • 2015-06-15
    • 2011-06-27
    相关资源
    最近更新 更多