18

で自分を変更しようとすると、次の例外が発生し@IDます@Entity

identifier of an instance of com.google.search.pagerank.ItemEntity was altered from 1 to 2.

テーブルの主キーを変更していることはわかっています。JPAアノテーションを使用しています。

この単一のHQLクエリを使用してこれを解決しました:update Table set name=:newName where name=:oldName

よりOOのアプローチを使用する代わりに:

beginTransaction();
T e = session.load(...);
e.setName(newName);
session.saveOrUdate(e);
commit();

差分が何であるかについて何か考えはありますか?

4

4 に答える 4

22

実際、JPA仕様によれば、主キーを変更することは禁止されています。

アプリケーションは主キーの値を変更してはなりません[8]。これが発生した場合の動作は未定義です。[9]

(EJB 3永続性(JPA)仕様、2.1.4項から)

于 2010-02-07T14:31:12.830 に答える
10

なぜあなたがそれをしたいのか想像できません。まったく。なぜエンティティのIDを変更するのですか?また、それを指す他のテーブルのすべての外部キーを更新する必要があります。痛みのようで、利益はありません。これを「ビジネスキー」(プレーンプロパティ)にして、より永続的な代理キーを使用する方がおそらく良いでしょう。私はあなたがこれについてすべて間違っていると感じています、しかしあなたが主張するならば...

基本的に、あなたがしているのは、新しい顧客を作成し、古い顧客を削除することです。それが、Hibernateでそれを達成する方法です。

[擬似コード]

Begin Transaction

// create new customer from old
newC = Session.Load<Customer>(42)
Session.Evict(newC)
newC.Id = 1492
Session.Save(newC)

// update other relationships to point to newC
// ....

// delete old customer
oldC = Session.Load<Customer>(42)
Session.Delete(oldC)

Commit Transaction

ただし、単純な単一のSQLトランザクションで一度に実行する方がおそらく良いでしょう。どちらの場合も、「古い」顧客のインスタンスがすでに存在する並列プロセスが発生するリスクがあり、エラーが発生する可能性があります。

于 2009-04-10T15:45:39.873 に答える
4

私の友人、あなたは正しいです。HQLステートメントを使用せずに主キーを変更する方法はありません(または方法がわかりません)。それは正常ではありませんが、本当です。

于 2009-06-12T09:04:20.253 に答える
3

私はそれが上で答えられたと信じているので、これは解決策ではありません。

しかし、私はこれをやりたいと思うための有効なシナリオであると私が考えたものを提供したかったのです。(コメント歓迎)

1)テーブルUSER_ELECTRONICSには、テーブルELECTRONICS_DEFとの多対多があります

2)この多対多は順序付きリストです。各USER_ELECTRONIC_IDには、ELECTRONICS_DEF_IDの優先リストがあります。たとえば、私はiPhone、iPad、携帯電話を持っていて、好きな順にランク付けしています。これを実現するために、次のようなUSER_ELEC_PRIORITY_MAPテーブルがあります-

USER_ELEC_ID ELEC_DEF_ID PRIORITY

1 IPAD 1
1 IPHONE 2
1 CELL 3

USER_ELEC_IDとELEC_DEF_IDはPFKです。PRIORITYはコンポジットFKです。

3)好みの観点からテーブルを再調整したい場合(新しいIPad2がリストの一番上にあり、iPadが#4に移動します)、Composite FK(PRIORITY)の一部を更新する必要があります。

于 2011-03-25T17:55:14.233 に答える