【发布时间】:2018-11-29 21:31:09
【问题描述】:
我有以下架构(缩写)
Comment id, content, createdBy
Attribute id, key, value (unique constraint on key, value)
CommentAttribute id, comment_id, attribute_id
所以这是一个相当简单的架构。
我已经用最简单的实体对 Comment 和 Attribute 实体进行了映射,所以我不会在这里发布代码。
CommentAttribute如下
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "comment_attributes")
public class CommentAttribute {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Cascade(value = {CascadeType.ALL})
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "comment_id", nullable = false)
private Comment comment;
@Cascade(value = {CascadeType.ALL})
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "attribute_id", nullable = false)
private Attribute attribute;
public Long getId() {
return id;
}
public CommentAttribute setId(final Long id) {
this.id = id;
return this;
}
public Comment getComment() {
return comment;
}
public CommentAttribute setComment(final Comment comment) {
this.comment = comment;
return this;
}
public Attribute getAttribute() {
return attribute;
}
public CommentAttribute setAttribute(final Attribute attribute) {
this.attribute = attribute;
return this;
}
}
目的是用户将添加具有一个或多个属性的评论。类似于下面缩写的 GraphQL
addComment(content: "a comment", [{name: "threadId" value: "thread1"}])
我正在使用 Spring JPA 和 Hibernate,所以我想对上面的内容进行建模,以便将记录添加到链接表中。我有一个测试如下:
@Test
public void whenAddingTwoCommentsWithSameAttributesThenNoDuplicateCreated() {
Comment comment = new Comment();
comment.setCreatedBy("user1");
comment.setContent("some test comment");
Attribute attribute = new Attribute();
attribute.setKey("threadId");
attribute.setValue("thread1");
CommentAttribute commentAttribute = new CommentAttribute();
commentAttribute.setComment(comment);
commentAttribute.setAttribute(attribute);
commentAttributeRepository.saveAndFlush(commentAttribute);
Comment comment2 = new Comment();
comment2.setCreatedBy("user1");
comment2.setContent("some test comment2");
Attribute attribute2 = new Attribute();
attribute2.setKey("threadId");
attribute2.setValue("thread1");
attribute2.setTenantId("customer1");
CommentAttribute commentAttribute2 = new CommentAttribute();
commentAttribute2.setComment(comment2);
commentAttribute2.setAttribute(attribute2);
commentAttributeRepository.saveAndFlush(commentAttribute2);
final List<CommentAttribute> all = commentAttributeRepository.findAll();
assertThat(all).hasSize(2);
assertThat(all.get(0).getComment().getContent()).isEqualTo("some test comment");
assertThat(all.get(0).getAttribute().getValue()).isEqualTo("thread1");
assertThat(all.get(1).getComment().getContent()).isEqualTo("some test comment2");
assertThat(all.get(1).getAttribute().getValue()).isEqualTo("thread1");
}
所以 attribute2 变量实际上是非唯一的。保存 commentAttribute2 时,我在属性表上遇到唯一约束冲突,这并不奇怪,因为 Hibernate 正在尝试插入新记录。
我希望 Hibernate 使用现有的属性记录(如果存在),否则创建一个新记录并使用它。有没有办法用注释来配置它?如果没有,我是否必须查找属性实体,如果没有找到则只创建一个新的?
【问题讨论】:
-
我不知道怎么做。您必须加载
Comment及其属性,并查看要添加的属性是否已存在于属性集中。如果是,什么都不做,如果不是,添加它。您还需要先查找Attribute,看看是否已经存在这样的属性。我不知道 JPA 有什么地方可以为你做这一切。另外,为什么连接表需要一个 id?为什么不在 Comment 实体上使用ManyToMany注释?
标签: java hibernate spring-data-jpa hibernate-mapping