2011-12-01 9 views
5

MySQLテーブルへのHibernateマッピングを介していくつかのJavaオブジェクトの永続性を実装しようとしています。私がコミットすると、「バッチ更新はupdate [0]から予期しない行数を返しました。実際の行数:0;期待される:1 '。HibernateでのMySQLへのマッピングの主キーとしてのLONG

私の仮説は、私のJava POJOにlong -fieldをMySQLテーブルのプライマリキーとして使用したいという問題が原因であるという仮説です。 MySQLテーブル(ERROR 1170:キー長なしでキー仕様で使用されるBLOB/TEXTカラム 'id')の主キーとしてデータ型LONGを使用できなかったので、私はいくつかのグーグルとこのpostから結論付けました。 longのマッピング。しかし、それは更新していません。

私のテストPOJO Personは非常に簡単です。

xml(person.hbm.xml)のhibernateマッピングは、基本的に次のようになります(マイナス( - ))。見出し):レコードを保存または更新することになっている

<hibernate-mapping> 
    <class name="hibernatetest.Person" table="hibernatetest"> 
    <id name="id" type="long" column="id" > 
    <generator class="native"/> 
    </id> 

    <property name="firstname"> 
    <column name="firstname" /> 
    </property> 
    <property name="lastname"> 
    <column name="lastname"/> 
    </property> 
</class> 
</hibernate-mapping> 

私の実際のJavaコードスニペットは単純です:

Transaction tr = session.beginTransaction();    
Person person = new Person(1,"John","Doe"); 
session.saveOrUpdate(person); 
tr.commit(); 

そして、ここではそのことだ、私はの種類を変更する場合は、このすべてがうまく動作しますidをPersonオブジェクトのint(Integer)とMySQLテーブルに追加します。しかし、私はその問題が残るように、私が残したいと思っている実際のオブジェクトにはその選択肢がありません。私は何が間違っているのですか、それを動作させるために何をすべきですか?ありがとう。

Hibernate: update hibernatetest set firstname=?, lastname=? where id=? 
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81) 
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73) 
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:57) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3006) 
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237) 
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:113) 
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:273) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:265) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1082) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:317) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175) 
    at com.hibernate.test.TestMain.main(TestMain.java:38) 
nested transactions not supported 

UPDATE: OK、私はそれを最後に出て働いているスタックトレースを追加すること

。私は、休止状態のジェネレータクラスを 'ネイティブ'から '割り当て済み'に変更し、現在は期待通りに動作します。だから今Hibernateマッピングは次のようになります。

<hibernate-mapping> 
    <class name="hibernatetest.Person" table="hibernatetest"> 
    <id name="id" type="long" column="id" > 
    <generator class="assigned"/> 
    </id> 

    <property name="firstname"> 
    <column name="firstname" /> 
    </property> 
    <property name="lastname"> 
    <column name="lastname"/> 
    </property> 
</class> 
</hibernate-mapping> 

私は(どこかからコピーされた)そのパラメータの意味を知っていて、それがこのくらいの頭痛を引き起こす可能性は思いもしませんでしたしませんでした認めなければなりません。このexplanationが見つかりました。これは非常に便利でした。

明らかに自分の質問に答えるための十分な資格がないため、開いたままになるか、誰かが空の回答を提供すると思います。私はそれを受け入れます。ありがとう。

+0

あなたはあなたの完全なstacktraceを投稿できますか?BIGINTは正常に動作するはずです。個人的に問題は見つかりませんでした。stacktraceを共有してください。 – mprabhat

+0

dbカラムタイプ定義は何ですか?あなたのid属性の種類は?とにかく、列のBigint、Javaの属性のLongは大丈夫です。 – polypiel

+0

@mprabhat完了。以前には見たことのない「ネストされたトランザクションはサポートされていません」というメッセージが表示されます。それが何を意味するかわからない? – hgus1294

答えて

5

あなたはそれが他の値である場合、オブジェクトのidがnullupdateある場合HibernateはINSERTクエリを発射saveOrUpdate()メソッドを使用します。コード Person person = new Person(1,"John","Doe");idから1に設定し、saveOrUpdate()メソッドを呼び出すことができます。 id 1のエントリがないと仮定しているため、エラーがスローされます。

動作させるには、以下の変更を行う必要があります。

  1. 変更longからLongの人でidのタイプ(ラッパークラスがnullをサポートできるようにするため)。

  2. コンストラクタnew Person("John","Doe");を書き込み、そのオブジェクトを保存します。

トランザクションデータのため<generator class="assigned"/>を保つために良いアイデアではありません。代わりに、最初に試していたとおりにnativeに固執する必要があります。

これは、別の解決策が見つかったとしても、これが最初の問題を解決するよりクリーンな方法だと思います。

+0

ありがとうございます。あなたは 'SaveOrUpdate'の前に' id' = 1で前のレコードが存在しなかったと仮定して正しいです。私はあなたの提案に応じてクラスの型を 'Long'に変更しようとしましたが、ジェネレータを' native'に設定すると同じエラーに戻ります。私はコンストラクタから 'id'を省略した2番目のポイントを理解できませんでしたか? 'id'は自動生成されたidではないので、特定の値に設定する必要があります。 – hgus1294

+0

私はあなたのDBにIDを選択させて、保存中のIDをハードコードしないようにしました。方法は[here](http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id)のオプションから選択してください。 – ManuPK

+0

OKです。私の実際のシナリオでは、 'id'は外部サービスから提供されているので、dbを決定させることはできません。クラスの型を 'Long'に変更し、' Long'を取るコンストラクタを保持すると、元の例外が得られます。それは予想どおりか、私は何か他のことを誤解しましたか?トランザクションに対してジェネレータ=「割り当て済み」のリスクを述べました。リスクとは何ですか? – hgus1294

関連する問題