2

QuestionとFavoritesCounterの2つのエンティティがあります。質問が初めてお気に入りに追加されるときに、FavoritesCounterを作成する必要があります。

2人のユーザーがお気に入りに質問を同時に追加しようとするユースケースを考えてみましょう。これにより、2番目のユーザーが呼び出された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

}

FavoriteCounter

@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 に答える