【问题标题】:Spring Boot REST JPA JSON formatSpring Boot REST JPA JSON 格式
【发布时间】:2016-09-19 11:21:13
【问题描述】:

我正在使用 Spring Boot 和 JPA 编写 REST 服务。我在带有复合键的表中有一对多映射。假设如果父表“订单”有 2 个复合键(订单 ID、销售日期),并且“订单明细”有该订单的多个项目,并有 3 个复合键(订单 ID、销售日期和项目 ID),我的请求对象应该如何处理是。我想知道是否可以不显式设置连接列属性并保留对象;就像我想发送以下 POST 有效负载并将其映射到 Order 对象。此映射不会为作为 OrderDetail 的复合键的 salesDate 和 orderId 设置值。因此,由于重复而持久化失败。

{
    "salesDate": "2016-02-12",
    "orderId": 12,
    "Description":"Sample order",
    "orderDetail":[{
      "itemId": 1231,
      "quantity": 2
    },
    {
      "itemId": 23342,
      "quantity": 1
    }]
}

Order.java:

@Entity
@Table(name = "ORDR")
@IdClass(OrderId.class)
public class Order implements Serializable {

    private static final long serialVersionUID = 2496620945369260577L;

    @Id
    @Column(name = "SLS_DT")
    private Date salesDate;

    @Id
    @Column(name = "ORDR_ID")
    private int orderId;

    @Column(name = "ORDR_DESC")
    private short orderDescription;

    @Column(name = "CUST_ID")
    private int customerId;

    @OneToMany(cascade= CascadeType.ALL, mappedBy = "order")
    private List<OrderDetail> orderItems;

    public Date getSalesDate() {
        return salesDate;
    }

    public void setSalesDate(Date salesDate) {
        this.salesDate = salesDate;
    }

    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    public short getOrderDescription() {
        return orderDescription;
    }

    public void setOrderDescription(short orderDescription) {
        this.orderDescription = orderDescription;
    }

    public int getCustomerId() {
        return customerId;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }
}

OrderId.java:

public class OrderId {

    private Date salesDate;
    private int orderId;

    public Date getSalesDate() {
        return salesDate;
    }
    public void setSalesDate(Date salesDate) {
        this.salesDate = salesDate;
    }
    public int getOrderId() {
        return orderId;
    }
    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }   
}

OrderDetail.java

@Entity
@Table(name= "ORDR_DTL")
@IdClass(OrderDetail.class)
public class OrderDetail implements Serializable{

    private static final long serialVersionUID = 3603127094767197954L;

    @Id
    @Column(name = "SLS_DT")
    private Date salesDate;

    @Id
    @Column(name = "ORDR_ID")
    private int orderId;

    @Id
    @Column(name = "ITEM_ID")
    private int itemId;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumns({@JoinColumn(name = "SLS_DT", referencedColumnName = "SLS_DT", insertable = false, updatable = false),
            @JoinColumn(name = "ORDR_ID", referencedColumnName = "ORDR_ID", insertable = false, updatable = false)})
    private Order order;

    private BigDecimal quantity;

    public Date getSalesDate() {
        return salesDate;
    }

    public void setSalesDate(Date salesDate) {
        this.salesDate = salesDate;
    }

    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    public int getItemId() {
        return itemId;
    }

    public void setItemId(int itemId) {
        this.itemId = itemId;
    }

    public BigDecimal getQuantity() {
        return quantity;
    }

    public void setQuantity(BigDecimal quantity) {
        this.quantity = quantity;
    }
}

OrderDetailId.java:

public class OrderDetailId implements Serializable {

    private static final long serialVersionUID = 2312835624801595602L;
    private Date salesDate;
    private int orderId;
    public Date getSalesDate() {
        return salesDate;
    }
    public void setSalesDate(Date salesDate) {
        this.salesDate = salesDate;
    }
    public int getOrderId() {
        return orderId;
    }
    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }
    public int getItemId() {
        return itemId;
    }
    public void setItemId(int itemId) {
        this.itemId = itemId;
    }
    private int itemId;
}

如果我通过以下 JSON,它会按预期工作。但我不想重复订单详情中的键,也不想将数据库结构暴露给客户端。

{
    "salesDate": "2016-02-12",
    "orderId": 12,
    "Description": "Sample order",
    "orderDetail": [{
        "salesDate": "2016-02-12",
        "orderId": 12,
        "itemId": 1231,
        "quantity": 2
    }, {
        "salesDate": "2016-02-12",
        "orderId": 12,
        "itemId": 23342,
        "quantity": 1
    }]
}

我可以传递第一个 json 并将其转换为 JPA 实体。但我相信应该有一个更清洁的方法。 JPA 文档在这种情况下没有多大帮助。请帮我解决这个问题。

【问题讨论】:

    标签: spring-boot jpa spring-data-jpa one-to-many spring-rest


    【解决方案1】:

    您可以尝试在OrderDetailIdorderId 成员上使用@JsonIgnore 注释。这应该会抑制 JSON 输出中的成员。

    @JsonIgnore
    private int orderId;
    

    还有类注解@JsonIgnoreProperties({"memberName"})。您不必在类源代码“内部”标记每个成员。

    @JsonIgnoreProperties({"orderId"})
    public class OrderDetail implements Serializable {
        ...
    

    【讨论】:

    • 感谢您的回复。我知道我们可以使用@JsonIgnore 进行响应。但我在这里谈论的是请求有效负载。我想发布保留的 json,而不将请求重新格式化为实际的数据库实体结构。
    猜你喜欢
    • 2021-08-28
    • 2023-03-15
    • 2019-01-19
    • 1970-01-01
    • 2017-04-19
    • 2018-08-24
    • 2021-05-16
    • 2017-12-15
    • 2021-12-13
    相关资源
    最近更新 更多