java - Spring-Boot JPA - 使用 JSON RequestBody 中的外键插入数据库会导致空对象

标签 java spring rest spring-boot spring-data-jpa

我正在尝试使用 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.
}

我的 Controller 方法是:

@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 时,它不会从 JSON 中获取 requestId 并将其转换为实体中的 ChangeRequest 对象。

我似乎找不到任何文档或教程或任何其他堆栈溢出问题来解决我的问题。我尝试使用不同的类作为 @RequestBody 但它只是返回空值。我已经在这个问题上坚持了两天,需要通过它,所以我将不胜感激任何人能够提供的帮助。

请原谅我的简短,我不得不匆忙发帖。如果您需要更多信息,请告诉我。

谢谢。

更新 - 答案

@user06062019 让我走上了正轨。我更正了提交的 JSON 并将 CascadeType.ALL 添加到实体中,但是,这给了我一个不同的错误 - 我无法将 null 插入到 ChangeRequest.pidm 中。

这是因为我在提交的 JSON 中将 requestId 作为外键,但是,它只需是 id,这就是 ChangeRequest 类中的参数的名称。然后,我可以检索 ChangeAuditService 中的 ChangeRequest 类,将其添加到 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"
}

最佳答案

您发送到的 json 似乎存在问题

createChangeAudit

ChangeAudit 对象需要 ChangeRequest 的对象类型,但请求 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 的映射

关于java - Spring-Boot JPA - 使用 JSON RequestBody 中的外键插入数据库会导致空对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56575939/

相关文章:

java - log4j2 Web 查找不工作

java - 设置基于 Spring security 的 OAuth2 服务器

java - 为什么无法从另一个类(其他 java 文件)访问按钮值?

java - Android 静态引用强吗

java - 如何使用 Java 将 RDF 文件上传到 Virtuoso

java - 这个使用模拟对象的 Spring 单元测试到底是如何工作的?

java - 泽西通用实体不工作

rest - 用于获取完整用户列表的 Jira Rest Api

java - Spring 异常 org.springframework.beans.factory.BeanCreationException

java - Collection 扩展了 Iterable,但为什么 Collection 声明 Iterable Function(与 Iterable 相同)