1

Hibernate JPA と Spring @Transactional(Atomikos JTA 実装) を使用すると、システムに次のエンティティがあります。

  • 注文
  • Orderline (注文への参照を保持)
  • お客様

I want to perform the following steps, in one transaction (これは 1 つのアトミック関数ブロックです) というaddOrder注釈が付けられた Service クラス メソッドで。@Transactional

  1. 注文を維持する
  2. オーダーラインを維持する
  3. 顧客を維持する

ステップ 1 (注文の永続化) で、JPA に任意の をロールバックさせますException

ステップ 2 (オーダーラインの永続化) で、オーダーラインの永続化中のエラーを無視したいと考えています。したがって、10 個のオーダーラインがあり、そのうちの 1 つが何らかの理由 (制約違反など) で失敗した場合、他のオーダーラインを続行したいと考えています。

ステップ3ExceptionでJPAにトランザクション全体をロールバックさせたい場合は、ステップ1と2で行ったすべてのこともロールバックします。

これまでに遭遇した問題:

  • の場合、JPA はトランザクションを「ロールバックのみ」としてマークしExceptionます。Exceptionしたがって、これより後 (および前) はすべてロールバックされますが、ステップ 2 では無視したいと思います。
  • flush()JPA は、 orcommit()が呼び出された後 (通常は@Transactionalメソッドが終了した後)にのみ制約違反を認識します。メソッド内でそれを知る必要があります。
  • 各ステップを別々の@Transactional方法に分割しようとしましたが、同じものを使用する必要があるためTransaction、前の 2 つの問題は変わりません。

これに最適なアプローチは何ですか?

アップデート

たとえば、すべての検証をJavaに入れ、レコードがすでに存在するかどうかを手動で確認する必要がありますか?

4

3 に答える 3

1

2番目の部分をtry-catchブロックに入れます。例: メソッド本体はおそらく次のようになります。

save(order);
flush();
for(Orderline line : orderlines) {
    try {
        orderlineService.save(line); 
        flush();   
    } catch(RuntimeException rte) {
        continue;
    }
}
save(customer);
于 2013-05-22T12:27:44.970 に答える
0

ステップ 2 (オーダーラインの永続化) で、オーダーラインの永続化中のエラーを無視したいと考えています。したがって、10 個のオーダーラインがあり、そのうちの 1 つが何らかの理由 (制約違反など) で失敗した場合、他のオーダーラインを続行したいと考えています。

@Transactional はデフォルトで REQUIRED です。各メソッド呼び出しは現在のトランザクションに参加し、3 つの操作すべてをアトミックにします。

ただし、この場合、REQUIRES_NEW を使用して再入可能なメソッドを作成し、各 Orderline を永続化するための新しいトランザクションを示す必要があります。

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void persistMyOrderLine(OrderLine o) throws Exception{}

オーダーラインを永続化する障害が別のオーダーラインに影響を与えてはならないため、それぞれに対して新しいトランザクションを作成する必要があります。そのため、TransactionA-OrderLineA を中止しても、TransactionB-OrderlineB には影響しません。

問題は次のとおりです。あなたのニーズでは、本質的に、操作はもはやアトミックではありません。失敗 (オーダーライン) が無視されるというシナリオがあるため、操作は ATOMIC ではなく、ロール プロセスを中止しません (3 つの手順)。

たぶん、これらのニーズを確認する必要があります。

于 2013-05-22T12:37:34.693 に答える
0

注文は必要ですか?ステップ 2 がステップ 3 になることはありますか?

その場合は、ステップ 1 と 3 を単一のトランザクションに入れ、各個人persist Orderlineを後で実行する独自のトランザクションに入れます。もちろん、すべてのオーダーラインが持続しない場合にロールバックする必要がある場合、これは機能しません...

別のアプローチは、エンティティを操作するためのアンマネージドEntityManagerを作成することです。Orderlineトランザクションを開始し、例外をキャッチし、コミット/ロールバックを自分で管理します。

理想的には、 JPA / JTA が直接サポートしていないネストされたトランザクションを使用します。外側のトランザクションのコミット/ロールバックを内側のトランザクションの成功/失敗に依存させるか、(あなたの場合は)内側のトランザクションを無視することで、ある程度の類似性を持つことができます。

「アトミシティ」は、実際には相対的な獣になる傾向があります。「トランザクション分離」の強度と選択した「ロックレベル」(変動を伴う楽観的または悲観的) に大きく依存します。

これに関する私の最初の考えは、スレッド同期の問題のようにこれに取り組み、入れ子の順序にある​​程度の一貫性を維持した場合 (「外側」は常に X を処理し、「内側」は常に「Y」を処理する)、変更が適用されるシリアル化された順序は一貫したままになるため、問題ありません。

于 2013-05-22T12:54:24.587 に答える