JPA @onetomany каскадная вставка выдает org.hibernate.exception.ConstraintViolationException - PullRequest
0 голосов
/ 17 января 2019

Класс прикрепления:

@Entity
@Table(name="attachments")
@Getter
@Setter
public class AttachmentModel {

    //@EmbeddedId
    //private AttachmentId attachmentId;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="notice_attachment_id")    
    private long attachmentId;

    @Column(name="notice_id")
    private long noticeId;

    @Column(name="attachment")
    private String attachmentUrl;

    @JsonIgnore
    @ManyToOne(cascade = {CascadeType.PERSIST , CascadeType.MERGE,
            CascadeType.DETACH , CascadeType.REFRESH},optional = false)
    @JoinColumn(name="notice_id", insertable=false, updatable=false)
    @MapsId("notice_id")
    NoticesModel notice;

    public void addNotice(NoticesModel notice) {
        this.notice = notice;
    }

    public AttachmentModel() {

    }   
}

Класс уведомлений:

@Entity
@Table(name = "notices")
@Getter @Setter
public class NoticesModel {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "notice_id" ,updatable = false, nullable = false,insertable = true)
    private long noticeID;

    @OneToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL } , mappedBy = "notice")
    //@mappedBy(name = "notice_id")
    private List<AttachmentModel> attachments;
}

Код для анализа JSON и его сохранения

public HashMap<String,Object> saveNotices(@RequestBody List<NoticesModel> tmpNotices)
    {
        List<NoticesModel> notices = tmpNotices;
        for (NoticesModel notice : notices) {
            List<AttachmentModel> attachments =  notice.getAttachments();
            for (AttachmentModel attachment : attachments) {
                attachment.addNotice(notice);
                System.out.println(attachment.getAttachmentUrl());
            }

            for (AttachmentModel attachment : attachments) {
                //attachment.addNotice(notice);
                System.out.println(attachment.getNotice().getContent());
                System.out.println(attachment.getNotice().getNoticeID());
            }
        }
        int result = noticesServices.saveNotice(notices);

        HashMap<String,Object> res = new HashMap<>();
        res.put("message",result);
        return res;

    }

Это мой JSON, который я отправляю

[
  {
    "attachments": [
      {
        "attachmentUrl": "/abc/bcd"
      }
    ],
    "content": "string",
  }
]

В этом случае я пытаюсь сохранить свое уведомление и приложение. в этом конкретном случае создается уведомление_id при сохранении в базу данных.

поэтому, пытаясь сохранить таблицу вложений, она пытается сохранить с параметром note_id, равным 0.

поэтому я получаю исключение.

не удалось выполнить оператор; SQL [н / п]; ограничение [attachments_notices_fk]; вложенное исключение: org.hibernate.exception.ConstraintViolationException: не удалось выполнить оператор

Как я могу решить эту проблему? Можно ли получить уведомление_id перед сохранением в БД, чтобы я мог получить note_id , чтобы я мог установить его во вложении, чтобы он не был сохранен с 0? Что я делаю неправильно (любой альтернативный подход, который я могу использовать) в этом случае (я довольно новичок в JPA и Springboot)?

1 Ответ

0 голосов
/ 17 января 2019

Я думаю, вам просто не нужно использовать notice_id. Удалите notice_id и соответствующие вещи из вашего AttachmentModel и используйте notice для отображения (ПРИМЕЧАНИЕ: после удаления все еще будет столбец notice_id в дБ), поэтому:

@ManyToOne
private NoticesModel notice;

и измените также отображение в NoticesModel для ссылки на правильное поле:

//                                    ALL is just a suggestion
@OneToMany(mappedBy = "noticesModel", cascade = CascadeType.ALL)
private List<AttachmentModel> attachementModels;

Тогда ваш цикл for может выглядеть так:

for (NoticesModel notice : notices) {
    for (AttachmentModel am : notice.getAttachments()) {
        am.setNotice(notice);
    }
    noticesServices.save(notice);
}

Вы также можете добавить что-то подобное в NoticesModel, чтобы всегда задавать настройку перед сохранением:

@PrePersist
private void prePersist() {
    for (AttachmentModel am : attachments) {
        am.setNotice(this);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...