4

Challengeクラスと多対1の関係にあるクラスがありUserます。単方向なので、次のようになります。

@Entity
@Table(name = "UserTable")
public class User {
   @Id
   private String userId;
}

@Entity
@Table(name = "ChallengeTable")
public class Challenge {
   @Id
   private String challengeId;

   @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
   @JoinColumn(name = "userId")
   private User user;
}

を使用しており、オブジェクトで のメソッドSpring Data JPAを使用する場合、そのユーザーがまだ存在しない場合はアタッチされたユーザーを永続化し、ユーザーが既に存在する場合は古いユーザーにマージします。saveCRUDRepositoryChallenge

を使用してユーザーを取得するためにのfindOne(String id)メソッドを使用しています。これが で設定しているユーザーです。UserRepositoryuserIdChallenge

ユーザーがまだ存在しない場合は問題なくカスケードされますが、既存のユーザーで保存しようとすると例外が発生します。

javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [com.mywebsite.model.User#zk9moo78sx685g6o9yphegdx6lpoll9x]

ここで何が間違っているのかわかりません。を変更しCascadeTypeALLも何も変わりません。最初にユーザーを完全に手動で保存して削除しようとしてCascadeTypeも機能しません。それは私にエラーを与えます:

org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: com.mywebsite.model.Challenge.user -> com.mywebsite.model.User

これは、トランザクションが終了したときに発生するようです (サービス層クラスに の注釈が付けられているため@Transactional)。

注釈を取り出して@Transactional手動でユーザーを永続化すると、すべて正常に動作するようです。(ただし、サービスレベルでのカスケード保存とトランザクションが必要です。)

を取り出して@Transactionalカスケード保存を使用しようとすると、SQLIntegrityConstraintViolationException例外が発生して失敗します。これはUser、 が切り離されたエンティティになり、新たに永続化しようとするが、主キーが既に存在するため失敗するためです。

ここで何が起こっているのかを理解するのを手伝ってくれる人はいSpring Data JPAますか?

4

1 に答える 1

0

CascadeType.SAVE_UPDATEハイバネート固有のカスケード オプションを使用してみましたが、他に考えられるすべてのものを使用しましたが、カスケード セーブをハイバネートの想定どおりに機能させることができませんでした。これは、Spring Data を使用した JPA の厳しい制限だと思います。

代わりに、サービスとインターフェイス リポジトリの間にレイヤーを追加しました。依存エンティティ (ユーザー) を保存してからチャレンジを保存します。

于 2013-05-03T17:39:41.913 に答える