由于密钥变更而尝试插入时,外键约束失败 [英] Foreign key constraint failure when trying to insert because of key change

查看:208
本文介绍了由于密钥变更而尝试插入时,外键约束失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Content对象,该对象引用ManyToMany关系中的一组Tag对象.作为持久存储新Content对象的一部分,我在PostgreSQL中查看Tag是否已经存在,如果存在,那么我将对它的引用添加到Content对象中并尝试保存Content对象.我遇到的问题是,执行此操作时,我会将标签与ID相关联,例如1和2与内容有关,当我尝试保存内容时,它失败并出现外键冲突,因为它说ID为10的标签不存在.我逐步执行了代码,当我将Tag添加到与Content关联的标签集中时,它具有正确的ID(即1和2),那么为什么在保存时将其更改为另一个ID?我正在使用JPA,Hibernate,Spring和PostgreSQL.我已经在下面附加了休眠的Content对象. "content_tag"表仅由content_id和tag_id组成,它们是对content和tag表的外键引用.需要说明的是:此实例中的标记已经创建,我只是通过在数据库中搜索它们并将它们的关联添加到内容中来添加该关联

I have a Content object which refers to a set of Tag objects in a ManyToMany relationship. As part of persisting a new Content object I look in PostgreSQL to see if the Tag already exists and if it does then I add the reference to it to the Content object and attempt to save the Content object. The issue I am having is that when I do this I am associating Tags with ids e.g. 1, and 2 with the Content and when I attempt to save the content it fails with a foreign key violation because it says Tag with id 10 does not exist. I stepped through the code and when I add the Tag to the set of tags associated with Content it has the correct id (i.e. 1 and 2) so why when I save it does it change to a different id? I am using JPA, Hibernate, Spring, and PostgreSQL. I've attached the hibernate Content object below. The "content_tag" table just consists of content_id and tag_id which is foreign key references to the content and tag tables. To clarify: the tags in this instance are already created and I am only adding the association by searching for them in the database and adding their association to the content

这是错误:

org.postgresql.util.PSQLException: ERROR: insert or update on table "content_tag" violates foreign key constraint "tag_id_fkey"
  Detail: Key (tag_id)=(12) is not present in table "tag".

显示尝试保存的代码:

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);

这是内容类:

@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.PERSIST,
            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);
    }
}

推荐答案

将内容实体中关系的配置更改为此:

change the configuration of your relation in content entity to this:

@JoinTable(name = "content_tag",
        joinColumns = @JoinColumn(name = "content_id"),
        inverseJoinColumns = @JoinColumn(name="tag_id")
)

这篇关于由于密钥变更而尝试插入时,外键约束失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆