有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何正确处理EntityExistsException?

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

考虑一个用例,当两个用户试图同时向收藏夹添加一个问题时,当第二个用户调用了^ {CD2>}时,这会导致^ {CD1>}。

但是下面的代码不起作用,因为当抛出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之后返回已创建实体的最佳方式是什么


共 (1) 个答案

  1. # 1 楼答案

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

    或者,您可以将createCounter()移动到FavoriteServiceBean的本地接口(同时确保添加@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(),以便容器知道如何启动新事务