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]
ここで何が間違っているのかわかりません。を変更しCascadeTypeてALLも何も変わりません。最初にユーザーを完全に手動で保存して削除しようとして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ますか?