我有两个实体:Question和收藏夹计数器。首次将问题添加到收藏夹时,应创建收藏夹计数器。

考虑一个用例,当两个用户试图同时向收藏夹中添加问题时-当第二个用户调用EntityExistsException时,这将导致entityManager.persist(counter)

但是下面的代码不起作用,因为抛出EntityExistsException时,容器将事务标记为仅回滚,并且尝试返回getFavoritesCounter(question)失败,并显示javax.resource.ResourceException: Transaction is not active

@Stateless
public class FavoritesServiceBean implements FavoritesService {

  ...

  public void addToFavorites(Question question) {
    FavoritesCounter counter = getCounter(question);
    if (counter == null) {
      counter = createCounter(question);
    }
    //increase counter
  }

  private FavoritesCounter createCounter(Question question) {
    try {
      FavoritesCounter counter = new FavoritesCounter();
      counter.setQuestion(question);
      entityManager.persist(counter);
      entityManager.flush();
      return counter;
    } catch (EntityExistsException e) {
      return getFavoritesCounter(question);
    }
  }

  private FavoritesCounter getFavoritesCounter(Question question) {
    Query counterQuery = entityManager.createQery("SELECT counter FROM FavoritesCounter counter WHERE counter.question = :question");
    counterQuery.setParameter("question", question);
    List<FavoritesCounter> result = counterQuery.getResultList();
    if (result.isEmpty()) return null;
    return result.get(0);
  }

}




@Entity
public class Question implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  //getter and setter for id

}


收藏夹计数器

@Entity
public class FavoritesCounter implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @OneToOne
  @Column(unique = true)
  private Question question;

  //getter and setter

}


EntityExistsException之后返回已创建的实体的最佳方法是什么?

最佳答案

您可以将createCounter()移到另一个Session Bean并用@TransactionAttribute(REQUIRES_NEW)标记该方法

另外,您也可以将createCounter()移到“ FavoritesServiceBean”的本地接口(还要确保添加了@TransactionAttribute(REQUIRES_NEW)批注)并按以下方式调用它:

@Stateless
public class FavoritesServiceBean implements FavoritesService
{

    ...
    @Resource
    protected SessionContext sessionContext;

    public void addToFavorites(Question question)
    {
        FavoritesCounter counter = getCounter(question);
        if (counter == null) {
          counter = sessionContext.getBusinessObject(FavoritesService.class)
                                  .createCounter(question);
        }
       //increase counter
    }

    @TransactionAttribute(REQUIRES_NEW)
    public FavoritesCounter createCounter(Question question)
    {
        ...
    }
    ...
}


您需要通过业务/本地接口,而不是直接调用createCounter(),以便容器知道开始新事务。

关于java - 如何正确处理EntityExistsException?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3037499/

10-13 04:17