0

私は現在、私のプロジェクトで楽観的ロック管理に取り組んでいます。JPA 2.0 (hibernate-jpa2.0-api-1.0.1.Final) を使用し、データソースは JBoss 7 によって提供されます。

私がしたこと

私のエンティティ「AccordSimple」では、@Version アノテーションを使用します。

@Entity
@Table(name = "AccordSimple")
public class AccordSimple {
    @Id
    @SequenceGenerator(name = "parametresubsidesequence", 
        sequenceName = "parametresubsidesequence", allocationSize = 1)  
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "parametresubsidesequence")
    private Long id;

    // Optimistic lock.
    @Version
    private Long version;

}

そして、これは私のAccordServiceImplです

public AccordDTO updateAccord(AccordDTO accordDTO) throws AppException {

    AccordSimple accord = getAccordRepository().findByReference(
            accordDTO.getAccordReference());

    if (accord == null) {
        return null;
    }

    // copy new values from the DTO...
    accord.setVariable(accordDTO.getVariable());
    // ... 

    // Set the version from the DTO (old version if someone changes before me!)
    accord.setVersion(accordDTO.getVersion());

    getAccordRepository().merge(accord);
    return accordDTO;
}

これにより、OptimisticLockException はスローされません。マージの直前にアコードに含まれていたバージョンが、私の DB のバージョンの下にあったとしても。

その理由がわかりました。これは責任者です:

    AccordSimple accord = getAccordRepository().findByReference(
            accordDTO.getAccordReference()); 

メソッドを次のように変更すると、

public AccordDTO updateAccord(AccordDTO accordDTO) throws AppException {

    AccordSimple accord = new AccordSimple(accordDTO.getAccordReference(), accordDTO.getVersion());

    // copy new values from the DTO...
    accord.setVariable(accordDTO.getVariable());
    // ... 

    // Set the version from the DTO (old version if someone changes before me!)
    accord.setVersion(accordDTO.getVersion());

    getAccordRepository().merge(accord);
    return accordDTO;
}

OptimisticLockException がスローされます。

問題

バージョンは、私の DTO からではなく、Hibernate キャッシュから取得されます。したがって、エンティティをデタッチすると、すべてが機能します(推測します)が、それはしたくありません(開発者がそれを忘れた場合のバグの原因...)。

何か考えはありますか?

4

1 に答える 1

1

[編集済み]考えられる代替案:まだ試していませんが、試してみることができます。

@PostLoadまたはinsertable=false、updateable = falseを指定した追加の列マッピングを使用して、エンティティに追加のバージョン番号を保持します。

@PreUpdateメソッドに、バージョンフィールドと追加バージョンフィールドのチェックを実行してもらいます。それらが一致しない場合は、例外をスローします。

これらはすべて基本モデルクラスに入れることができます。したがって、誰もロジックをエンティティに入れることを忘れません:)


(オリジナルメッセージ)

これはまさに私の前のプロジェクトで直面したことです。Hibernateは、オプティミスティックロック検証を実行するときにエンティティのバージョンフィールドを調べていません。

私がその時間を解決した方法は、DTOをエンティティに「マージ」するときに自分自身を確認することです。その時、私はDTOとエンティティの間でプロパティをマップするユーティリティを持っています。バージョンチェックは、DTOのバージョンフィールドに追加の注釈を付けるだけで、対応するエンティティのプロパティに値を設定する代わりに、一致しない場合に例外をスローします。

おそらくあなたには当てはまりません


于 2012-05-31T09:51:24.850 に答える