3

複数フィールドの一意の制約を持つ永続クラスがあります。しかし、定義された一意の制約は私には十分ではありません.1つのフィールドでは、等しくないが類似の値も一意であるためです。

メソッドを実装していcheckUniqueConstraintます。DAO クラスの add メソッドと update メソッドでは、checkUniqueConstraintpersist オブジェクトを追加または更新する前に呼び出します。

checkUniqueConstraintメソッドは、SELECTクエリを実行して入力に似たオブジェクトを見つけ、いくつかのものを見つけるチェック例外をスローします。

public class PersistClassDao {    
public void checkUniqueConstraint(PersistClass persistObject) throws DuplicateEntityException {
    /**
    * creating a query string that find persist objects similar to input parameter.
    **/
    try {
        PersistClass result = (PersistClass) query.uniqueResult();
        if(result != null && (persistObject.getId() == null  || persistObject.getId() != result.getId())){
            throw new DuplicateEntityException(exceptionMessage, "");
        } 
    } catch (NonUniqueResultException e) {
        throw new DuplicateEntityException(exceptionMessage);
    }
}

public long add(/* field of new persistObject*/) throws DuplicateEntityException {
    //creates a transisent instance of persistObject
    PersistClass newObject = getPersistClass(/* field of new persistObject*/);
    checkUniqueConstraint(newObject);
    try {
        getCurrentSession().save(newObject);
        getCurrentSession().flush();
        return newObject.getId();
    } catch (ConstraintViolationException e) {
        throw new DuplicateEntityException();
    }
}

追加用のトランザクションサービスメソッドと更新用のトランザクションサービスメソッドがあります。

テストを実行すると

  • 最初に 2 つの persistObjects を追加します (サービス メソッドを使用)。
  • 次に、(サービスメソッドを介して)一方を更新して、他方と同様になるようにします
  • DuplicatException がスローされることを期待しています

しかし、実際には org.hibernate.exception. checkUniqueConstraint によって ConstraintViolationException がスローされます!!

なんで?

4

3 に答える 3

4

問題はFlushModeにあるはずです。デフォルトでは、Hibernate はクエリを実行する前にエンティティをフラッシュします。 http://docs.jboss.org/hibernate/core/3.5/javadocs/org/hibernate/FlushMode.html#AUTOを参照してください。

新しいエンティティを部分的に初期化し、セッションにバインドされたエンティティに関連付けて、クエリを実行しようとする必要があります。Hibernate セッションはクエリの直前にフラッシュを実行し、ConstraintViolationException で失敗しますが、これは問題ありません。

解決:

  1. アプリケーション全体の cfg ファイルでFlushModeCOMMITに変更し、
  2. session.setFlushMode(FlushMode.COMMIT )または
  3. query.setFlushMode(FlushMode.COMMIT)を呼び出すことで、変更の影響を単一のクエリに絞り込むことができます。
于 2013-01-15T08:53:41.140 に答える
0

PersistClass内部のゲッターまたはセッターは、単純な get/set ロジックではないと思われます。ゲッターが Hibernate がセッターに渡したものと同じインスタンスを返さない場合、Hibernate はトランザクションの完了時に「ダーティ」エンティティをフラッシュします。

PersistClassコードと Hibernate ログを貼り付けて検証できますか?

于 2012-12-30T13:14:05.493 に答える