JPA @onetomany cascade insert is throwing org.hibernate.exception.ConstraintViolationException

问题: Attachement class: @Entity @Table(name="attachments") @Getter @Setter public class AttachmentModel { //@EmbeddedId //private AttachmentId attachmentId; @Id...

问题:

Attachement class:

@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() {

    }   
}

Notices class:

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

Code to parse JSON and saving it

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;

    }

This is my JSON I am sending

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

For this case I am trying to save save my notice and attachment. in this particular case notice_id is getting created while saving to database.

so while trying to save attachement table it is trying to save with notice_id as 0.

so I am getting the exception.

could not execute statement; SQL [n/a]; constraint [attachments_notices_fk]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

How I can be able to solve this issue? Is this possible to get the notice_id before saving to DB so that I can get notice_id so that I can set it in attachment so that it will not be saved with 0? What am I doing wrong(Any alternative approach I can take) in this case(I am pretty new to JPA and springboot)?


回答1:

I think you just should not need to use any notice_id. Remove notice_id and relevant things from your AttachmentModel and usenotice for mapping (NOTE: there will still be column notice_id in db after removal), so:

@ManyToOne
private NoticesModel notice;

and change also the mapping in the NoticesModel to refer to the correct field:

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

Then your for loop might look like:

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

You could also add something like this in your NoticesModel to handle setting the reference always before persisting:

@PrePersist
private void prePersist() {
    for (AttachmentModel am : attachments) {
        am.setNotice(this);
    }
}
  • 发表于 2019-01-18 22:24
  • 阅读 ( 501 )
  • 分类:网络文章

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除