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
を使用する場合、そのユーザーがまだ存在しない場合はアタッチされたユーザーを永続化し、ユーザーが既に存在する場合は古いユーザーにマージします。save
CRUDRepository
Challenge
を使用してユーザーを取得するためにのfindOne(String id)
メソッドを使用しています。これが で設定しているユーザーです。UserRepository
userId
Challenge
ユーザーがまだ存在しない場合は問題なくカスケードされますが、既存のユーザーで保存しようとすると例外が発生します。
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
ますか?