我正在运行具有两个实体的最新版本的Hibernate:Project
和ProjectShare
,它们具有双向设置的一对多关系。
ProjectShare
由包含project_id
和user_id
的复合ID唯一标识。除了键之外,ProjectShare
包含一个布尔型标志,无论用户对项目具有读取或写入访问权限。
@Entity
@Table(name = "projects")
public class Project {
@Id
@GeneratedValue // UUID generator
@Column(name = "project_id")
private String id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProjectShare> shares = new ArrayList<>();
public Project(String name) {
this.name = name;
}
public void addShare(ProjectShare share) {
shares.add(share);
share.setProject(this);
}
public void removeShare(ProjectShare share) {
shares.remove(share);
share.setProject(null);
}
}
@Entity
@Table(name = "project_shares")
public class ProjectShare {
@EmbeddedId
private ProjectShareId id;
@Column(name = "has_write_access")
private boolean hasWriteAccess;
@MapsId("projectId")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "project_id", nullable = false, updatable = false)
private Project project;
public ProjectShare(ProjectShareId id, boolean hasWriteAccess) {
this.id = id;
this.hasWriteAccess = hasWriteAccess;
}
public void setProject(Project project) {
this.project = project;
}
}
@Embeddable
public class ProjectShareId implements Serializable {
@Column(name = "project_id")
private String projectId;
@Column(name = "user_id")
private String userId;
public ProjectShareId(String userId) {
this.userId = userId;
}
// equals and hashCode go here...
}
如果我创建一个新的Project
并为其分配新的ProjectShare
关联,则一切正常:
Project project = new Project("my_project");
project.addShare(new ProjectShare(new ProjectShareId("user1"), false));
project.addShare(new ProjectShare(new ProjectShareId("user2"), false));
projectRepository.save(project); // assume project id is '123'
由于所有对象都是新的并且尚未持久化,因此它将为Project本身执行1次插入,并为每个ProjectShare执行1次插入。假设插入的项目ID为“ 123”。
现在,如果我加载此现有项目,并向其添加新的ProjectShares,则会出现问题:
Project project = projectRepository.findById("123");
project.addShare(new ProjectShare(new ProjectShareId("user2"), true));
project.addShare(new ProjectShare(new ProjectShareId("user3"), true));
projectRepository.save(project);
对于每个ProjectShare,此操作将对ProjectShareId
(project_id和user_id)中的值执行SELECT,然后执行INSERT UPDATE(取决于是否找到记录)。这是Hibernate的基本合并策略,这就是我们想要的。
期望的结果应该是:
user1
的ProjectShare user2
的ProjectShare(从false
到true
)user3
创建一个新的ProjectShare 但是,当对ProjectShare
执行SELECT时,外键project_id始终为空。这意味着将永远找不到现有记录,尝试使用INSERT代替UPDATE,并触发数据库级约束违反。
我应该如何解决此问题?我应该手动浏览project.getShares()
集合,查找现有记录并更新它们吗?我希望Hibernate通过其合并策略来做到这一点。
或者这可能是Hibernate中与嵌入ID中的外键关联相关的错误吗?