2

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

考虑两个用户同时尝试将问题添加到收藏夹的用例 - 这将导致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

4

1 回答 1

2

您可以将 createCounter() 移动到另一个会话 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() 以便容器知道开始新事务。

于 2010-06-14T16:46:36.590 回答