我很难理解这个JPA行为,这对我来说似乎并不符合规范。 我有2个基本实体:
public class User {
@Id
@Column(name = "id", unique = true, nullable = false, length = 36)
@Access(AccessType.PROPERTY)
private ID id;
@OrderBy("sequence ASC")
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = { CascadeType.REMOVE })
private final Set<UserProfile> userprofiles = new HashSet<UserProfile>(0);
//Ommiting rest of fields since they aren't relevant
}
public class UserProfile {
@Id
@Column(name = "id", unique = true, nullable = false, length = 36)
@Access(AccessType.PROPERTY)
private ID id;
@NotNull
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "userID", nullable = false, foreignKey = @ForeignKey(name = "FK_UserProfile_User"))
private User user;
//Ommiting rest of fields since they aren't relevant
}
如您所见,我只有级联设置为REMOVE,如果我没有设置级联设置,行为将是相同的。
现在,如果我打电话:
User user = new User();
user.setId(UUIDGenerator.generateId());
UserProfile userProfile = new UserProfile();
userProfile.setId(UUIDGenerator.generateId());
userProfile.setUser(user);
user.getUserProfiles().add(userProfile);
em.merge(user);
merge会抛出异常。
我看到Hibernate正在对UserProfile表执行SQL查询: 选择userprofil0_.userProfileID作为userProf1_4_0_,userprofil0_.profileID作为profileI3_4_0_,userprofil0_.sequence作为sequence2_4_0_,userprofil0_.userID作为userID4_4_0_来自UserProfile userprofil0_,其中userprofil0_.userProfileID =?
然后它会抛出异常 org.springframework.orm.jpa.JpaObjectRetrievalFailureException:找不到标识为6aaab891-872d-41e6-8362-314601324847的com.mytest.domain.UserProfile;
为什么甚至会调用此查询?
由于我没有在userprofiles中将cascade类型设置为MERGE,我的期望是JPA / Hibernate会忽略userprofiles set中的实体并且只插入/更新用户记录,不会这样做反对JPA规范?
如果我将cascadetype更改为MERGE,则会按预期工作,并且User和UserProfile都将添加到数据库中,因此没有问题。让我感到困惑的是,为什么Hibernate会查询数据库并错误地发现一个根本不应该合并的实体,因为我没有将它设置为级联。
这更像是我遇到的一个学术场景,当然我可以简单地清除用户配置集并且事情会起作用,但我试图理解为什么上述行为会发生,因为我可能缺少关于合并如何工作的一些关键信息。无论是否设置级联类型,它似乎总是会尝试将所有实体附加到会话中。
答案 0 :(得分:0)
为什么甚至会调用此查询?
这是因为您正在尝试合并实体,在JPA中使用merge()来创建实体managed/attached。要“合并”用户,JPA仍然需要维护它所拥有的引用(UserProfile)。在你的情况下,它并没有试图坚持UserProfile
试图获得它的引用来合并User
。阅读here
如果使用persist而不是merge,则不应该这样做。