Я пытаюсь сохранить записи в таблицу базы данных, которая включает внешний ключ в другую таблицу, используя Spring-Boot и Spring Data JPA.
Мой JSON выглядит так:
{
"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"
}
Моя сущность выглядит так:
@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.
}
Мой метод контроллера:
@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);
}
Я получаю следующую ошибку:
{
"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"
}
Что вызвано:
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}'}
]
Таким образом, при сохранении ChangeAudit
он не берет requestId
из JSON и не переводит его в объект ChangeRequest
в Entity.
Кажется, я не могу найти какую-либо документацию, учебник или любой другой вопрос о переполнении стека, который решает мою проблему. Я пытался использовать другой класс в качестве @RequestBody
, но он просто возвращает нулевые значения. Я застрял на этом в течение двух дней, и мне нужно его пройти, поэтому буду признателен за любую помощь, которую кто-либо может предложить.
Простите за краткость, пришлось поторопиться с публикацией. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.
Спасибо.
Обновление – ответ
@ user06062019 поставил меня на правильный путь. Я исправил отправленный JSON и добавил CascadeType.ALL в Entity, однако это дало мне другую ошибку: я не мог вставить null в ChangeRequest.pidm.
Это связано с тем, что у меня был requestId в качестве внешнего ключа в отправленном JSON, однако он должен был быть просто идентификатором, как называется параметр в классе ChangeRequest. Затем я мог бы получить класс ChangeRequest в ChangeAuditService, добавить его в объект ChangeAudit и сохранить. Вуаля!
Правильный 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"
}
Либо ChangeRequest
уже должен существовать в БД, либо вам нужно получить объект ChangeRequest
и установить его в ChangeAudit
перед сохранением.
@Suresh Я знаю, это то, чего я не могу достичь. Я не могу понять, как получить объект ChangeAudit
из внешнего ключа (requestId
)
@ user06062019 Я еще не написал класс ControllerAdvice. Ошибка возникает из-за встроенной обработки/проверки ошибок из аннотации @NotNull
в Entity. –
@Cyntech печатает changeAudit.toString() requestId? Создайте репозиторий ChangeRequest, который представляет ваш объект ChangeRequest. Если requestId имеет значение null, это означает, что объект не существует в базе данных и может обработать ошибку. В другом случае, когда requestId не равен нулю, вызовите findById репозитория ChangeRequest и получите объект объект, установите этот объект объекта в ChangeAudit.
Кажется, есть проблема в json, который вы отправляете в
createChangeAudit
Объект ChangeAudit ожидает тип объекта для запроса на изменение, и этот тип объекта отсутствует в запросе json.
Поэтому, если вы измените свой запрос на что-то подобное, он не должен жаловаться на ошибку проверки, а об остальном позаботится spring-data automagic.
{
"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
}
}
Также вам может понадобиться упомянуть о сопоставлении @ManyToOne с cascade= CascadeType.ALL
Не могли бы вы опубликовать метод, как сохранить объект. Исключение говорит, что changeRequest не должен быть нулевым. Возможно, вам потребуется установить объект changeRequest для объекта перед сохранением.