【问题标题】:Can't parse JSON object and insert it into database无法解析 JSON 对象并将其插入数据库
【发布时间】:2019-12-09 07:21:08
【问题描述】:

JSON 对象解析有问题。 JSON 代表用户下的订单。

这在以前是可行的,但是向项目添加额外的实体/DTO 会导致一些问题。更具体地说,JSON 如下所示:

{
    "orderElements": [
        {
            "product": {
                "id": 3,
                "name": "xxx",
                "description": "yyy",
                "category": {
                    "id": 2,
                    "name": "xxx"
                },
                "price": 11,
                "count": 1
            },
            "quantity": 1
        }
    ],
    "user": {
        "id": 110,
        "lastName": "xxx",
        "firstName": "xxx",
        "addressLine": "xxx",
        "city": "xxx",
        "country": "xxx",
        "zipCode": "123456",
        "phoneNumber": "1234567",
        "password": "xxxx",
        "email": "xxxx",
        "roles": [
            "USER"
        ]
    },
    "orderPlaceTime": null,
    "deliveryAddress": {
        "street": "xxx",
        "city": "xxx",
        "zipCode": "xxx"
    }
}

如果在没有“deliveryAddress”部分的情况下发送,JSON 将被正确解析并且一切正常。但尝试使用“deliveryAddress”发送 JSON 及其所有内容会导致 NullPointerException

虽然调试前端显示整个JSON 已正确填写 - 街道、城市和邮政编码字段包含用户输入的所有数据(以上正是“POST”发送的内容 - “orderPlaceTime”已填写后端通过LocalDateTime.now()函数)。

订购

@Entity
@Table(name = "carts")
public class Order extends AbstractEntity {

    @Fetch(FetchMode.SELECT)
    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "id_order")
    @JsonIgnore
    private Set<OrderElement> orderElements;

    @Column
    private LocalDateTime orderPlaceTime;

    @ManyToOne
    @JoinColumn(name = "id_user")
    private User user;

    @ManyToOne
    @JoinColumn(name = "id_delivery")
    private DeliveryAddress deliveryAddress;

    public DeliveryAddress getDeliveryAddress() {
        return deliveryAddress;
    }

    public void setDeliveryAddress(DeliveryAddress deliveryAddress) {
        this.deliveryAddress = deliveryAddress;
    }

    public Set<OrderElement> getOrderElements() {
        return orderElements;
    }

    public void setOrderElements(Set<OrderElement> orderElements) {
        this.orderElements = orderElements;
    }

    public LocalDateTime getOrderPlaceTime() {
        return orderPlaceTime;
    }

    public void setOrderPlaceTime(LocalDateTime orderPlaceTime) {
        this.orderPlaceTime = orderPlaceTime;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

}

交货地址

@Entity
@Table(name = "delivery_address")
public class DeliveryAddress extends AbstractEntity {

    @Column
    private String street;

    @Column
    private String city;

    @Column
    private String zipCode;

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

}

订单转换器

@Component
public class OrderConverter implements Converter<Order, OrderDTO> {

    private final OrderElementConverter orderElementConverter;
    private final DeliveryAddressConverter deliveryAddressConverter;
    private final UserConverter userConverter;

    public OrderConverter(OrderElementConverter orderElementConverter, DeliveryAddressConverter deliveryAddressConverter, UserConverter userConverter) {
        this.orderElementConverter = orderElementConverter;
        this.deliveryAddressConverter = deliveryAddressConverter;
        this.userConverter = userConverter;
    }

    @Override
    public Order convertToEntity(OrderDTO dto) {
        Order order = new Order();
        order.setId(dto.getId());
        order.setUser(userConverter.convertToEntity(dto.getUser()));
        order.setOrderPlaceTime(now());
        Set<OrderElement> entitySet = new HashSet<>();
        for (OrderElementDTO o : dto.getOrderElements()) {
            entitySet.add(orderElementConverter.convertToEntity(o));
        }
        order.setOrderElements(entitySet);
    // this below throws NullPointerException --> dto.getDeliveryAddressDTO();
        order.setDeliveryAddress(deliveryAddressConverter.convertToEntity(dto.getDeliveryAddressDTO()));
        return order;
    }
}

交货地址转换器

@Component
public class DeliveryAddressConverter implements Converter<DeliveryAddress, DeliveryAddressDTO> {

    @Override
    public DeliveryAddress convertToEntity(DeliveryAddressDTO dto) {
        DeliveryAddress deliveryAddress = new DeliveryAddress();
        deliveryAddress.setId(dto.getId());
        deliveryAddress.setCity(dto.getCity());
        deliveryAddress.setZipCode(dto.getZipCode());
        deliveryAddress.setStreet(dto.getStreet());
        return deliveryAddress;
    }
}

如果前端发送正确,我不知道为什么deliveryAddress 为空。

感谢您的所有回答和建议

编辑

事实证明,OrderDTO 中的 JB Nizet 字段具有“deliveryAddressDTO”而不是“deliveryAddress”。从名称中删除“DTO”解决了这个问题:

public class OrderDTO extends AbstractDTO {

    private Set<OrderElementDTO> orderElements;

    private LocalDateTime orderPlaceTime;

    private UserDTO user;

    private DeliveryAddressDTO deliveryAddress;
    // private DeliveryAddressDTO deliveryAddressDTO; <-- wrong name, methods also aligned

    public DeliveryAddressDTO getDeliveryAddress() {
        return deliveryAddress;
    }

    public void setDeliveryAddressDTO(DeliveryAddressDTO deliveryAddress) {
        this.deliveryAddress = deliveryAddress;
    }


    public Set<OrderElementDTO> getOrderElements() {
        return orderElements;
    }

    public void setOrderElements(Set<OrderElementDTO> orderElements) {
        this.orderElements = orderElements;
    }

    public LocalDateTime getOrderPlaceTime() {
        return orderPlaceTime;
    }

    public void setOrderPlaceTime(LocalDateTime orderPlaceTime) {
        this.orderPlaceTime = orderPlaceTime;
    }

    public UserDTO getUser() {
        return user;
    }

    public void setUser(UserDTO user) {
        this.user = user;
    }
}

【问题讨论】:

  • 你能分享一下DeliveryAddressConverter类吗?订单不能为空等等。所以看起来 deliveryAddressConverter 可能为空。
  • 现在添加了:)
  • 如何解析 JSON 以使其成为 OrderDTO?这个 DTO 的代码在哪里?请注意,JSON 中的属性名为 deliveryAddress,但 OrderDTO 中的字段似乎名为 deliveryAddressDTO
  • 所以事实证明,在 OrderDTO 中,我确实使用了 deliveryAddressDTO 作为字段名。但现在 SQL 抛出:org.springframework.dao.DataIntegrityViolationException:无法执行语句; SQL [不适用];约束 [null];嵌套异常是 org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause java.sql.SQLIntegrityConstraintViolationException: Column 'id_delivery' cannot be null"
  • 您在将 DeliveryAddress 设置到订单之前没有保存它,并且关联上没有级联。

标签: json hibernate spring-boot spring-data-jpa


【解决方案1】:

事实证明,OrderDTO 中的 JB Nizet 字段具有“deliveryAddressDTO”而不是“deliveryAddress”。从名称中删除“DTO”解决了这个问题:

public class OrderDTO extends AbstractDTO {

    private Set<OrderElementDTO> orderElements;

    private LocalDateTime orderPlaceTime;

    private UserDTO user;

    private DeliveryAddressDTO deliveryAddress;
    // private DeliveryAddressDTO deliveryAddressDTO; <-- wrong name, methods also aligned

    public DeliveryAddressDTO getDeliveryAddress() {
        return deliveryAddress;
    }

    public void setDeliveryAddressDTO(DeliveryAddressDTO deliveryAddress) {
        this.deliveryAddress = deliveryAddress;
    }


    public Set<OrderElementDTO> getOrderElements() {
        return orderElements;
    }

    public void setOrderElements(Set<OrderElementDTO> orderElements) {
        this.orderElements = orderElements;
    }

    public LocalDateTime getOrderPlaceTime() {
        return orderPlaceTime;
    }

    public void setOrderPlaceTime(LocalDateTime orderPlaceTime) {
        this.orderPlaceTime = orderPlaceTime;
    }

    public UserDTO getUser() {
        return user;
    }

    public void setUser(UserDTO user) {
        this.user = user;
    }
}

JB Nizet 也修复了 id_delivery 问题 - 向 ManyToOne 添加 cascade.ALL 注释解决了所有问题。

谢谢!

【讨论】:

    猜你喜欢
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多