我正在尝试建立一个与此处显示的系统非常相似的系统:
https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/
使用以下所示的内容类以相同的方式设置PostgreSQL模式,映射到具有content_id和tag_id的表中的标记类,这些表在其各自的表上具有外键约束。我遇到的问题是尝试保留新的内容对象时,我正在检查对象的标签是否存在,如果存在,则使用addTag方法添加它们,然后保留对象。否则,我将创建它们并保留该对象。执行此操作的POST方法也如下所示。存储库成功找到了标记,因为它们已经被保留了,但是当我尝试随后保留内容时出现以下错误: org.postgresql.util.PSQLException:错误:在表上插入或更新
"content_tag" violates foreign key constraint "tag_id_fkey"
Detail: Key (tag_id)=(11) is not present in table "tag".
我逐步执行了代码,并使用addTag方法将标记添加到内容中时,它表明它们的ID与数据库中已经存在的标记匹配,所以我不明白为什么当我保留内容时它是一个不同的ID。有谁知道我如何防止这种情况的发生并让内容持续存在?
@Entity(name = "Content")
@Table(name = "content")
@TypeDef( name= "StringJsonObject", typeClass = StringJsonUserType.class)
public class Content implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Type(type = "StringJsonObject")
@Column(name = "text")
private String text;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@ManyToMany(cascade = {
CascadeType.MERGE
})
@JoinTable(name = "content_tag",
joinColumns = @JoinColumn(name = "tag_id"),
inverseJoinColumns = @JoinColumn(name="content_id")
)
private Set<Tag> tags = new HashSet<>();
public Set<Tag> getTags() {
return tags;
}
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
public void addTag(Tag tag) {
tags.add(tag);
tag.getContents().add(this);
}
public void removeTag(Tag tag) {
tags.remove(tag);
tag.getContents().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Content)) return false;
return id != null && id.equals(((Content) o).getId());
}
@Override
public int hashCode() {
return 31;
}
}
@Entity(name = "Tag")
@Table(name = "tag")
public class Tag implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(name = "name")
private String name;
@ManyToMany(mappedBy = "tags")
private Set<Content> contents = new HashSet<>();
public Tag() {}
public Tag(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Content> getContents() {
return contents;
}
public void setContents(Set<Content> contents) {
this.contents = contents;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
return Objects.equals(name, tag.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
@PostMapping(value = "/content", consumes = { MediaType.APPLICATION_JSON_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE })
public ContentJSON createContent(@RequestBody(required = false) final String payload) {
if (StringUtils.isEmpty(payload)) {
throw new IllegalArgumentException(ServiceErrorCode.INVALID_REQUEST_BODY);
}
final ContentRequest request = convertPayloadToRequest(payload, ContentRequest.class);
final Content content = new Content();
content.setText(request.getContent().getText().toString());
for (final String tag : request.getContent().getTags()) {
final List<Tag> current = tagRepository.findByName(tag);
if (current.isEmpty()) {
final Tag newTag = new Tag(tag);
tagRepository.save(newTag);
content.addTag(newTag);
} else {
content.addTag(current.get(0));
}
}
final Content response = contentRepository.save(content);
Set<String> tagNames = new HashSet<>();
for (final Tag tag : content.getTags()) {
tagNames.add(tag.getName());
}
return new ContentJSON(response, tagNames);
}
答案 0 :(得分:0)
问题是下面的注释。
@JoinTable(name = "content_tag",
joinColumns = @JoinColumn(name = "content_id"),
inverseJoinColumns = @JoinColumn(name="tag_id")
)
joinColumns和inverseJoinColumns被反转