Spring-Boot JPA - вставка в БД с внешними ключами в JSON RequestBody приводит к пустому объекту - PullRequest
1 голос
/ 13 июня 2019

Я пытаюсь сохранить записи в таблицу базы данных, которая включает внешний ключ в другую таблицу, используя 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 в сущности.

Я не могу найти какую-либо документацию или учебник или любой другой вопрос переполнения стека, который решает мою проблему. Я попытался использовать другой класс как @RequestBody, но он просто возвращается с нулевыми значениями. Я застрял на этом два дня и мне нужно пройти его, поэтому буду признателен за любую помощь, которую кто-либо сможет предложить.

Простите за краткость, мне пришлось срочно отправлять сообщения. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Спасибо.

Обновление - Ответ

@ user06062019 поставьте меня на правильный путь. Я исправил отправленный JSON и добавил CascadeType.ALL к сущности, однако это вызвало у меня другую ошибку - я не мог вставить ноль в ChangeRequest.pidm.

Это потому, что в отправленном JSON у меня был requestId в качестве внешнего ключа, однако это должен был быть просто id, то есть то, что называется параметром в классе ChangeRequest. Затем я мог бы получить класс ChangeRequest в ChangeAuditService, добавить его в объект ChangeAudit и сохранить его. Voila!

Правильный 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"
}

1 Ответ

2 голосов
/ 13 июня 2019

Кажется, есть проблема в json, который вы отправляете на

createChangeAudit

Объект ChangeAudit ожидает тип объекта для ChangeRequest, и этот тип объекта отсутствует в запросе json.

Таким образом, если вы измените свой запрос на что-то подобное, он не должен жаловаться на ошибку валидации, а остальное позаботится автоматикой spring-data.

{

    "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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...