【发布时间】:2013-05-01 21:35:03
【问题描述】:
我有一个Challenge 类,它与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,当我对CRUDRepository 对象使用CRUDRepository 中的save 方法时,如果该用户尚不存在,我希望它保留附加用户,并且如果旧用户已经存在,则将该用户合并到旧用户中。
我在UserRepository 中使用findOne(String id) 方法来获取使用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 中的事务时获得级联保存?
【问题讨论】:
-
可以发一下你的服务方式吗?
-
您是否为实体创建了 hashcode 和 equals 方法?
-
我在两个实体上缺少哈希码和等于,但修复它并没有解决问题。
-
服务层实际上只是做一些事情,比如设置创建和更新日期。它使用 findOne(id) 来获取旧的,并确保挑战归正确的用户所有。
标签: java spring hibernate jpa spring-data-jpa