6

obj を永続化するときに、そのフィールドの 1 つが大きすぎて db フィールドに収まらないことがあり、その結果、データ切り捨て例外が発生します。次のコードでは、DataException をキャッチしてフィールドを空にし、再保存しようとしています。ただし、再保存すると例外が発生します。バッチ更新の例外が発生する理由と回避方法を教えてください。

 public static void save(Object obj) throws Exception{
        試す{
            beginTransaction();
            getSession().save(obj);
            commitTransaction();

        }キャッチ(例外e){
            e.printStackTrace();
            ロールバックトランザクション();
            eを投げます。
        }最後に{
            closeSession(); // 必要ありません。sf.getCurrentSession() から取得したセッションは自動的に閉じます
        }
    }   
 public static void saveXXX(XXX rec){

        試す {
            保存(記録);
        } catch (org.hibernate.exception.DataException e) {
            e.printStackTrace();

            saveXXX(rec, e); //例外を発生させます      
        キャッチ(例外e){
            e.printStackTrace();
        }

    }
    private static void saveXXX(WhoisRecord rec, DataException e) {
        rec.setField(""); //問題フィールドを空にする
        saveXXX(記録);

例外:

org.hibernate.StaleStateException: バッチ更新が更新から予期しない行数を返しました [0]; 実際の行数: 0; 予想: 1
    org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85) で
    org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70) で
    org.hibernate.jdbc.BatchingBatcher.checkRowCounts (BatchingBatcher.java:90) で
    org.hibernate.jdbc.BatchingBatcher.doExecuteBatch (BatchingBatcher.java:70) で
    org.hibernate.jdbc.AbstractBatcher.executeBatch (AbstractBatcher.java:268) で
    org.hibernate.jdbc.AbstractBatcher.prepareStatement (AbstractBatcher.java:114) で
    org.hibernate.jdbc.AbstractBatcher.prepareStatement (AbstractBatcher.java:109) で
    org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement (AbstractBatcher.java:244) で
    org.hibernate.persister.entity.AbstractEntityPersister.update (AbstractEntityPersister.java:2382) で
    org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert (AbstractEntityPersister.java:2335) で
    org.hibernate.persister.entity.AbstractEntityPersister.update (AbstractEntityPersister.java:2635) で
    org.hibernate.action.EntityUpdateAction.execute (EntityUpdateAction.java:115) で
    org.hibernate.engine.ActionQueue.execute (ActionQueue.java:279) で
    org.hibernate.engine.ActionQueue.executeActions (ActionQueue.java:263) で
    org.hibernate.engine.ActionQueue.executeActions (ActionQueue.java:168) で
    org.hibernate.event.def.AbstractFlushingEventListener.performExecutions (AbstractFlushingEventListener.java:321) で
    org.hibernate.event.def.DefaultFlushEventListener.onFlush (DefaultFlushEventListener.java:50) で
    org.hibernate.impl.SessionImpl.flush (SessionImpl.java:1027) で
    org.hibernate.impl.SessionImpl.managedFlush (SessionImpl.java:365) で
    org.hibernate.transaction.JDBCTransaction.commit (JDBCTransaction.java:137) で
.
.
.

4

5 に答える 5

3

私はこれについて専門家ではありませんが、同じ問題が反対方向にあったと思います。

レコードを保存しようとすると、Hibernate がそのデータ切り捨て例外をスローします。これは、必要なものすべてではなく、何かを保存したことを意味します。したがって、その例外をキャッチして、トランザクションをロールバックしようとします。しかし、これは常に成功することが保証されているわけではありません ( Hibernate save() および transaction rollbackで見たものから)。そのため、保存されたデータがまだそこにある可能性があります。だとしましょう。次に、レコードを変更して、再度保存を試みます。

しかし、データはまだそこにあるので、save を呼び出しても何もしません。その場合は更新でなければなりません。したがって、そのトランザクションをコミットしようとすると、Hibernate は 1 レコードを保存する必要があることを認識しますが、0 を保存することに成功するため、エラーが発生します。

getSession().save(obj); を変更してみてください。getSession().saveOrUpdate(obj);に . レコードが存在しない場合はレコードを保存し、存在する場合は (オーバーラージ フィールドを持たないように) 更新する必要があります。

于 2011-09-15T22:50:03.083 に答える
3

クラス マッピングのキーのジェネレーターが間違っていたため、このエラーが発生しました。その後、同じトランザクションで最初に挿入を行い、後で更新を行いました。

キー列は自動インクリメント (MySQL で) として定義され、このマッピングで

<id name="tableId" type="long" access="field">
   <column name="tableId" />
   <generator class="assigned" />
</id>

StaleStateException が発生しましたが、エントリを次のように修正すると、

<id name="tableId" type="long" access="field">
   <column name="tableId" />
   <generator class="native" />
</id>

その後は問題なく動作しました。

于 2012-03-13T12:57:47.203 に答える
2

正確に伝えるには十分な手がかりがありません。同じ問題があり、save() の代わりに merge() を呼び出すことで解決したと言えます。オブジェクトが分離されている場合は、常に merge() を使用する必要があります。

于 2011-04-01T21:26:06.623 に答える
1

これは、マッピング ファイルから取得されます。ネイティブ ジェネレーター クラスは、Oracle のシーケンスにマップされます。シーケンスを作成するか(使用したベース名はわかりませんが、休止状態のドキュメントにあると思います)、別のジェネレーターに切り替えます。

ネイティブから割り当て済みに変更しましたが、例外は発生しませんが、オブジェクトはデータベースに永続化されません。

http://forum.spring.io/forum/spring-projects/data/19856-not-Saving-in-an-oracle-data-base

于 2014-04-20T08:09:24.587 に答える
1

私が経験したことは、オブジェクトを更新するときにこの例外が発生し、テーブルに存在しない ID を持つことです。例外メッセージを読むと、「バッチ更新が更新から予期しない行数を返しました [0]; 実際の行数: 0; 予想: 1」と表示されます。これは、指定された ID のレコードが見つからなかったことを意味します。

これを回避するために、レコードが見つかった場合は常に同じIDのレコードを読み取り、それ以外の場合は「例外レコードが見つかりません」をスローします。

于 2014-05-22T10:59:50.380 に答える