1

まず第一に、永続化ユニットを変更できないため、この解決策は私にとって選択肢ではありません。

私の問題は、JTA EntityManager を使用していることですが、トランザクションのようなユースケースが 1 つだけ必要です。

public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod)
{
    //TODO use transaction here 
    super.save(pointsValidityPeriod);

    if (updatePrevious(pointsValidityPeriod.getValidFrom()) != 1)
    {
        logger.error("Update of Period was not possible, because UPDATE returned no single result.");

        return false;
    }

    pointsValidityPeriodEvent.fire(pointsValidityPeriod);

    return true;
}

保存方法(変更できません):

public void save(T entity)
{
    getEntityManager().persist(entity);
}

保存呼び出しがあることがわかりますが、更新が失敗した場合、この保存をロールバックする必要があります。どうすればそれを達成できますか? 何か案は?

4

2 に答える 2

1

それはすべて、メソッドのトランザクション注釈に依存します。何も持っていない場合、デフォルトでは、トランザクション境界は JB が指すビジネス メソッドに設定されます。

したがって、メソッド全体が 1 つのトランザクションです。通常、saveメソッドのトランザクション管理は重要です (REQUIREDまたはの場合は違いREQUIRES_NEWます) が、この場合はビジネス メソッド呼び出しではなくローカル メソッド呼び出しを行っているため、saveメソッドのトランザクション管理設定は適用されません。ここ。

したがって、update失敗した場合は、自動トランザクション ロールバック (Tx をロールバックする例外を生成する EntityManager 呼び出しの場合) に基づくか、手動で挿入SessionContextして呼び出すことができますsetRollbackOnly()

@Resource
SessionContext ctx;

public boolean saveWithResult(PointsValidityPeriod pointsValidityPeriod)
{
   // ...
    if (updatePrevious(pointsValidityPeriod.getValidFrom()) != 1)
    {
        // ...
        ctx.setRollbackOnly();
        // ...
    }
}
于 2012-06-27T11:44:20.170 に答える
0

解決策はありますが、なぜこれが機能するのかわかりません。誰かが私に説明してくれるかもしれません。私のバッキング Bean には save メソッドがあります。2 つのエンティティがあります。getEntity() は、バッキング Bean によって使用される現在のエンティティです。currentValidityPeriod は、currentValidityPeriod = pointsValidityService.findCurrent(); によってフェッチされた、エンティティの最新のデータベース状態を保持するエンティティの別のインスタンスです。findCurrent() は、TypedQuery を実行する単なるメソッドです。

public PointsValidityPeriod findCurrent()
{
    TypedQuery<PointsValidityPeriod> validityPeriodQuery = entityManager.createNamedQuery(PointsValidityPeriod.FindCurrent, PointsValidityPeriod.class);

    return validityPeriodQuery.getSingleResult();
}

これは、ビューによって呼び出される保存メソッドです。ご覧のとおり、現在のエンティティのみをサービスの save メソッドに渡します。前のエンティティ (currentValidityPeriod) では、別の値を設定しました。

@Override
public void save()
{       
    Date validFrom = new DateTime(DateTimeZone.forID("Europe/Vienna")).toDate();
    getEntity().setValidFrom(validFrom);

    currentValidityPeriod.setValidThru(validFrom);

    pointsValidityService.save(getEntity());

    addSavedSuccessfullyMessage();
}

これは、呼び出されるサービス メソッドです。

@Override
public void save(PointsValidityPeriod pointsValidityPeriod)
{
    super.save(pointsValidityPeriod);
}

...そしてスーパークラスの save メソッド:

public void save(T entity)
{
    getEntityManager().persist(entity);
}

Entity Manager が新しいエンティティを保持し、古いエンティティを更新するのはなぜですか? Entity Manager に 1 つのエンティティを渡すだけです。これは予想される動作ですが、なぜこれが機能するのか知りたいです。

于 2012-06-28T07:14:05.487 に答える