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