Ошибка ограничения внешнего ключа при попытке вставить из-за изменения ключа - PullRequest
1 голос
/ 31 октября 2019

У меня есть объект Content, который ссылается на набор объектов Tag в связи ManyToMany. Как часть сохранения нового объекта Content, я смотрю в PostgreSQL, чтобы увидеть, существует ли тег, и если он существует, я добавляю ссылку на него в объект Content и пытаюсь сохранить объект Content. Проблема, с которой я сталкиваюсь, заключается в том, что, когда я делаю это, я связываю теги с идентификаторами, например, 1 и 2, с контентом, и когда я пытаюсь сохранить контент, происходит сбой с нарушением внешнего ключа, поскольку он говорит, что тег с идентификатором 10 не существует. ,Я прошел через код, и когда я добавляю тег в набор тегов, связанных с контентом, он имеет правильный идентификатор (т. Е. 1 и 2), так почему, когда я сохраняю его, он изменяется на другой идентификатор? Я использую JPA, Hibernate, Spring и PostgreSQL. Я прикрепил объект Content в спящем режиме ниже. Таблица "content_tag" состоит только из content_id и tag_id, которые являются ссылками внешнего ключа на таблицы содержимого и тегов. Чтобы уточнить: теги в этом экземпляре уже созданы, и я только добавляю ассоциацию, ища их в базе данных и добавляя их ассоциацию к контенту

Вот ошибка:

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

Ответы [ 2 ]

2 голосов
/ 31 октября 2019

измените конфигурацию вашего отношения в сущности контента на это:

@JoinTable(name = "content_tag",
        joinColumns = @JoinColumn(name = "content_id"),
        inverseJoinColumns = @JoinColumn(name="tag_id")
)
0 голосов
/ 31 октября 2019

Это вызвано транзакцией, U не может прочитать незафиксированные данные, U может совершить транзакцию после того, как U создаст строку с тегом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...