5

文字列型と1対多の関係にあるユーザーオブジェクトがあります。単純なマッピングだと思います。typesテーブルは、関連付けられたuser_idと変数の型名を保持します。主キー「id」は基本的にカウンターです。

<class name="Users" table="users">
    <id column="id" name="id" />
    ...
    <set name="types" table="types" cascade="save-update">
        <key column="id" />
        <one-to-many class="Types" />
    </set>
</class>

<class name="Types" table="types">
    <id column="id" name="id" />
    <property column="user_id" name="user_id" type="integer" />
    <property column="type" name="type" type="string" />
</class>

これは、データベースに追加するために使用したJavaです。

User u = new User();
u.setId(user_id);
...
Collection<Types> t = new HashSet<Types>();
t.add(new Type(auto_incremented_id, user_id, type_name));
u.setTypes(t);

getHibernateTemplate().saveOrUpdate(u);

実行すると、次のエラーが発生します。

61468 [http-8080-3] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1062, SQLState: 23000
61468 [http-8080-3] ERROR org.hibernate.util.JDBCExceptionReporter - Duplicate entry '6' for key 'PRIMARY'
61468 [http-8080-3] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update

SQLを確認すると、次のように表示されます。

Hibernate: insert into users (name, id) values (?, ?)
Hibernate: insert into types (user_id, type, id) values (?, ?, ?)
Hibernate: update types set id=? where id=?
  • HibernateがタイプのIDを更新しようとするのはなぜですか?

エラーは次のように述べています。キー「PRIMARY」のエントリ「6」が重複していますが、実際にはありませんか?IDが毎回インクリメントされることを確認しました。そして、ユーザーとタイプがデータベースに正しく追加されます。

入ってくる情報を記録しましたが、追加されたタイプのIDは7、ユーザーIDは6です。Hibernateがuser_idを6にして、タイプを更新し、id=6を設定しようとした可能性があります。したがって、重複する主キーエラー?

しかし、なぜそれはそんなに奇妙なことをするのでしょうか?更新を停止する方法はありますか?

  • IDを手動で設定する必要がありますか?そうでない場合、どのようにタイプを追加する必要がありますか?タイプ文字列のみを含み、IDを含まないタイプオブジェクトを追加すると、他のエラーが発生します。

みんなありがとう。何日もそれを熟考してきました...

4

2 に答える 2

2

最大の問題は、<key>マッピングの列が正しくないことです。「id」ではなく「user_id」にする必要があります。そうは言っても、あなたのマッピング全体は私には少し奇妙に思えます。

まず第一に、ID を自動生成したい場合は、適切なジェネレーターを指定して Hibernate に任せるべきです:

<id column="id" name="id">
   <ジェネレータ クラス="ネイティブ"/>
 </id>

利用可能なさまざまなオプションについては、ジェネレーターに関する Hibernate のドキュメントを参照してください。

次に、文字列型のセットだけが必要な場合は、それらを 1 対多の関係ではなく、要素のコレクションに再マッピングすることを検討してください。

<set name="types" table="types">
    <key column="user_id"/>
    <element column="type" type="string"/>
 </セット>

そうすれば、明示的な「タイプ」クラスやそのマッピングは必要ありません。「タイプ」に追加の属性が必要な場合でも、エンティティではなくコンポーネントとしてマップできます。

最後に、説明していない要件のために「タイプ」がエンティティである必要がある場合、「ユーザー」と「タイプ」の間の関係は双方向であり、次のようにマッピングする必要があります。

<set name="types" table="types" inverse="true">
    <key column="user_id"/>
    <one-to-many class="タイプ"/>
 </セット>

 ...
 型マッピング:
 <many-to-one name="user" column="user_id" not-null="true"/>

後者の場合、「Types」には「Users」タイプの「user」プロパティが必要です。 詳細な例を次に示します。

于 2009-07-09T21:55:46.573 に答える
0

私にとってうまくいった解決策は、(タイプをユーザーに追加せずに)2つの部分を別々に保存することでした:

getHibernateTemplate().save(user);
getHibernateTemplate().save(new Type(user.id, type_name));

そして、タイプ ID のみに < generator class="native" /> を使用します。

悪い習慣?

要素のコレクションとしてマップしていましたが、user_id を types id 列に誤って追加していたため、重複エラーが発生することがありました。types id が唯一の主キー列であるためです。変!他の列エラーがあったことを覚えていますが、すぐに 1 対多に戻したので忘れてしまいました。Hibernate の奇妙な仕組みが理解できませんでした...

いつか双方向ソリューションを試してみます...すべての助けに感謝します:)

于 2009-07-10T14:33:08.283 に答える