Java Spring Boot JPA-在JSON RequestBody中使用外键插入DB会导致空对象

Java Spring Boot JPA-在JSON RequestBody中使用外键插入DB会导致空对象,java,spring,rest,spring-boot,spring-data-jpa,Java,Spring,Rest,Spring Boot,Spring Data Jpa,我正试图使用SpringBoot和SpringDataJPA将记录保存到一个数据库表中,该数据库表包含另一个表的外键 我的JSON如下所示: { "requestId": 10080, "auditType": "C", "auditDate": "2019-06-12T17:25:43.511", "auditUsername": "cdunstal", "message": "Lorem ipsum dolor sit amet, consectetu

我正试图使用SpringBoot和SpringDataJPA将记录保存到一个数据库表中,该数据库表包含另一个表的外键

我的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.
}
我的实体如下所示:

{
    "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
时,它不会从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
    }


}

另外,您可能需要提到cascade=CascadeType的@ManyToOne映射。所有

您是否可以将该方法发布为您保存实体的方式。异常说明changeRequest不应为null。您可能需要在保存之前将changeRequest对象设置为实体。
changeRequest
应该已经存在于数据库中,或者您需要获取
ChangeRequest
对象,并在坚持之前在
ChangeAudit
中设置它。@Suresh我知道,这是我无法实现的。我不知道如何从外键(
requestId
)@user06062019获取
ChangeAudit
对象我还没有编写ControllerAdvice类。错误来自实体中
@NotNull
注释的内置错误处理/验证@Cyntech是否执行changeAudit.toString()打印请求ID?创建表示您的ChangeRequest实体的ChangeRequest存储库。如果requestId为null,则表示该实体在数据库中不存在,并且可以处理错误。在另一种情况下,如果requestId不为null,则调用ChangeRequest存储库的findById并获取实体对象,将此实体对象设置为ChangeAudit。