Spring-Boot JPA – Inserting into a database using a foreign key in JSON RequestBody results in an empty object
I’m trying to use Spring-Boot and Spring Data JPA to save records to a database table that contains a foreign key for another table.
My JSON looks like this:
{
"requestId": 10080,
"auditType": "C",
"auditDate": "2019-06-12T17:25:43.511",
"auditUsername": "cdunstal",
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eget porttitor velit. Fusce libero augue, tincidunt in vestibulum nec, lobortis tristique eros. Cras tempor est magna, eu dapibus metus bibendum non.",
"isReportable": "Y"
}
My entity looks like this :
@Entity
@Table(name = "CHANGE_AUDIT")
@SequenceGenerator(name = "CHANGE_AUDIT_PK_SEQ", sequenceName = "CHANGE_AUDIT_PK_SEQ", allocationSize = 1)
public class ChangeAudit {
@Column(name = "AUDIT_ID")
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CHANGE_AUDIT_PK_SEQ")
private Integer id;
@Version
private Long version;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REQUEST_ID")
@NotNull
private ChangeRequest changeRequest;
@Column(name = "AUDIT_TYPE", nullable = false, length = 1)
@NotNull
@Size(max = 1)
private String auditType;
@Column(name = "AUDIT_DATE", nullable = false)
@NotNull
private Date auditDate;
@Column(name = "AUDIT_USER", nullable = false, length = 10)
@NotNull
@Size(max = 10)
private String auditUsername;
@Column(name = "AUDIT_MESSAGE", nullable = false, length = 4000)
@NotNull
@Size(max = 4000)
private String message;
@Column(name = "IS_REPORTABLE", nullable = false, length = 1)
@NotNull
@Size(max = 1)
private String isReportable;
Constructor, getters and setters omitted.
}
My Controller method is:
@RequestMapping(value = "/changeAudit/create", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody()
public ChangeAudit createChangeAudit(@RequestBody ChangeAudit changeAudit) {
logger.info("Creating new ChangeAudit: " + changeAudit.toString());
return this.changeAuditService.createChangeAudit(changeAudit);
}
I get the following error:
{
"timestamp": 1560412164364,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.transaction.TransactionSystemException",
"message": "Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction",
"path": "/grade-admin-api/changeAudit/create"
}
This is due to:
Caused by: javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:87)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
... 78 common frames omitted
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [au.edu.csu.gradeadmin.api.entity.ChangeAudit] during persist time for groups [ javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=changeRequest, rootBeanClass=class au.edu.csu.gradeadmin.api.entity.ChangeAudit, messageTemplate= '{javax.validation.constraints.NotNull.message}'}
]
Therefore, when you save ChangeAudit
, it does not get the requestId from the
JSON and convert it to a ChangeRequest
object in the entity.
I can’t seem to find any documentation or tutorials or any other stack overflow issue that solves my issue. I tried using a different class as @RequestBody
but it just returns null. I’ve been holding out for two days and need to get through it, so thank you very much for anyone who might be able to help.
Forgive me for my brevity, I had to rush to post. Please let me know if you need more information.
Thank you.
Update – Answer
@user06062019 Get me on the right track. I corrected the submitted JSON and added CascadeType.ALL to the entity, however, this gave me a different error – I couldn’t insert null into ChangeRequest.pidm.
This is because I use requestId as a foreign key in the submitted JSON, however, it only needs to be id, which is what the parameter in the ChangeRequest class calls. I can then retrieve the ChangeRequest class in ChangeAuditService, add it to the ChangeAudit object, and save it. And voila!
Correct JSON:
{
"changeRequest": {
"id": 10080
},
"auditType": "C",
"auditDate": "2019-06-12T17:36:43.511",
"auditUsername": "someuser",
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eget porttitor velit. Fusce libero augue, tincidunt in vestibulum nec, lobortis tristique eros. Cras tempor est magna, eu dapibus metus bibendum non.",
"isReportable": "Y"
}
Solution
There seems to be something wrong with the json
you sent to
createChangeAudit
The ChangeAudit object requires the object type of ChangeRequest, which is missing from the request json.
So if you change the request to something like this, it shouldn’t prompt a validation error, and the spring-data automagic will handle the rest.
{
"auditType": "C",
"auditDate": "2019-06-12T17:25:43.511",
"auditUsername": "cdunstal",
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eget porttitor velit. Fusce libero augue, tincidunt in vestibulum nec, lobortis tristique eros. Cras tempor est magna, eu dapibus metus bibendum non.",
"isReportable": "Y",
"changeRequest":{
"requestId": 10080
}
}
You may also want to mention @ManyToOne mapping with cascade= CascadeType.ALL