2009-05-22 10 views
3

私は、ツリーをデータベースに更新するプロセスを持っています。そうすることで、重複したエンティティをチェックするための読み込みが実行されます。Hibernateがfind-not-nullエラーでflushを呼び出す

私は、このプロセスを介して)(criteria.uniqueResultをやろうとしている途中では、次のエラーが発生することを発見しています:

スタックトレースを掘り

org.hibernate.PropertyValueException: not-null property references a null or transient value

、私はuniqueResult()が紅潮していることを見ますセッションを開始し、まだデータベースに移動する準備ができていない更新を実行しようとしています。

at org.hibernate.engine.Cascade.cascade(Cascade.java:153) 
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154) 
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145) 
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) 
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58) 
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:996) 
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1589) 
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306) 
at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:328) 
at com.inversion.dal.BaseDAO.findUniqueByCriterion(BaseDAO.java:59) 

ここに何か間違いがありますか?

大変助かりました。

Marty

答えて

3

オブジェクトを含む休止状態を保存する必要があります。選択した休止状態を発行すると、これらの変更がフラッシュされます。これにより、selectが正しい結果を返すことが保証されます。

FlushModeをFlushMode.AUTO以外の値に設定すると、この動作が防止されます。しかし、エラーはあなたのコードにあります。そこでは、不完全なオブジェクトを渡して、永続化または更新するために休止状態にします。だから、正しい解決策は、オブジェクトが完了したら、後でそのオブジェクトを渡して休止状態にすることです。

+0

不完全なオブジェクトをhibernateに渡すのはnull制約違反の良い候補ですが、そのようなエラーを引き起こす可能性のあるコードパスがたくさんあり、既にセッション内にあるアイテムの変更と関係があります。エラーが発生しています。 – Jherico

2

この例外を修正するには、セッションオブジェクトの自動フラッシュをオフにします。

Session s; 
// if you're doing transactional work 
s.setFlushMode(FlushMode.COMMIT); 
// if you want to control flushes directly 
s.setFlushMode(FlushMode.MANUAL); 

これはエラーではありません。あなたのコードの前の何かがメモリ内のオブジェクトを無効な状態にしてしまい、autoflush中にDBに永続化しようとしています。

+0

私はトランザクション境界をマークするために注釈を使用しています。@Transactional(readOnly = false)これは私のコードの中で手動ではなく、境界を処理するのに好ましい方法だと思いましたか? また、エンティティは無効な状態ですが、まだコミットする準備が整っていません.HibernateはSELECT中にそれを自分自身で実行しています。どうして? –

+1

トランザクション中であるという理由だけでも、SQLがデータベースに対して実行されないというわけではありません。 FlushModeは、トランザクションがコミットされたときではなく、SQLが実行されるときを制御します。データベースに関する限り、無効な状態のオブジェクトを作成する場合は、後でJhericoが提案する方法でフラッシングを延期する必要があります。 –

0

私はこれらの問題の底に到達しようと何度も私の髪を引っ張ってきました。問題はそれを引き起こしている問題の根底に到達することがとても難しいということです。

あなたはあなたのウィットに近づいている場合、あなたはまた、新しいセッションでfindAllよう支援するクエリを実行することができ、エンド:

Domain.withNewSession { session -> ... } 

通常、ほとんどの場合、私のために問題を回避しています。

関連する問題