Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring Jackson通过Id引用现有对象来反序列化对象_Java_Json_Spring_Jackson_Deserialization - Fatal编程技术网

Java Spring Jackson通过Id引用现有对象来反序列化对象

Java Spring Jackson通过Id引用现有对象来反序列化对象,java,json,spring,jackson,deserialization,Java,Json,Spring,Jackson,Deserialization,我有以下三个实体类: 装运实体: @Entity @Table(name = "SHIPMENT") public class Shipment implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "SHIPMENT_ID", nullable = false) private in

我有以下三个实体类:

装运实体:

@Entity
@Table(name = "SHIPMENT")
public class Shipment implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "SHIPMENT_ID", nullable = false)
    private int shipmentId;

    @Column(name = "DESTINATION", nullable = false)
    private String destination;

    @OneToMany(mappedBy = "shipment")
    private List<ShipmentDetail> shipmentDetailList;
    
//bunch of other variables omitted

    public Shipment(String destination) {
        this.destination = destination;
        shipmentDetailList = new ArrayList<>();
    }
产品实体:

@Entity
@Table(name = "Product")
public class Product implements Serializable {

    @Id
    @Column(name = "PRODUCT_ID", nullable = false)
    private String productId;

    @Column(name = "PRODUCT_NAME", nullable = false)
    private String productName;

//bunch of other variables omitted 

    public Product() {
    }

    public Product(String productId, String productName) {
        this.productId = productId;
        this.productName = productName;
    }
我通过RESTAPI接收JSON。问题是我不知道如何使用shipmentDetails反序列化一个新的装运,shipmentDetails仅通过ID与现有对象建立关系。我知道您可以简单地使用objectmapper反序列化,但这要求每个shipmentDetail中都包含product的所有字段。如何仅使用productID进行实例化

已收到JSON示例

{
    "destination": "sample Dest",
    "shipmentDetails": [
        {
            "productId": "F111111111111111"
        },
        {
            "productId": "F222222222222222"
        }
    ]
}
当前,我的rest端点将接收JSON,并执行以下操作:

public ResponseEntity<String> test(@RequestBody String jsonString) throws JsonProcessingException {
        JsonNode node = objectMapper.readTree(jsonString);
        String destination = node.get("destination").asText();
        Shipment newShipment = new Shipment(destination);
        shipmentRepository.save(newShipment);

        JsonNode shipmentDetailsArray = node.get("shipmentDetails");
        int shipmentDetailsArrayLength = shipmentDetailsArray.size();
        for (int c = 0; c < shipmentDetailsArrayLength; c++) {
            String productId = node.get("productId").asText();
            Product product = productRepository.findById(productId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No product with ID of: " + productId + " exists!"));
            ShipmentDetail shipmentDetail = new ShipmentDetail(newShipment, product, quantity);
            shipmentDetailRepository.save(shipmentDetail);
        }
    }
public ResponseEntity测试(@RequestBody String jsonString)抛出JsonProcessingException{
JsonNode节点=objectMapper.readTree(jsonString);
字符串destination=node.get(“destination”).asText();
装运新闻装运=新装运(目的地);
shipmentRepository.save(newShipment);
JsonNode shipmentDetailsArray=node.get(“shipmentDetails”);
int shipmentDetailsArrayLength=shipmentDetailsArray.size();
对于(int c=0;cnew ResponseStatusException(HttpStatus.NOT_FOUND,“没有ID为“+productId+”的产品存在!”);
ShipmentDetail ShipmentDetail=新的ShipmentDetail(新装运、产品、数量);
shipmentDetailRepository.save(shipmentDetail);
}
}
我想做的是:

public ResponseEntity<String> test2(@RequestBody String jsonString) throws JsonProcessingException {
    
    JsonNode wholeJson = objectMapper.readTree(jsonString);
    Shipment newShipment = objectMapper.treeToValue(wholeJson, Shipment.class);
    
    return new ResponseEntity<>("Transfer Shipment successfully created", HttpStatus.OK);
}
public ResponseEntity test2(@RequestBody String jsonString)抛出JsonProcessingException{
JsonNode wholeJson=objectMapper.readTree(jsonString);
Shipping newShipment=objectMapper.treeToValue(wholeJson,shipping.class);
返回新的响应属性(“已成功创建转运”,HttpStatus.OK);
}
我尝试了这个解决方案,但没有成功:

如何使产品实体搜索现有产品,而不是尝试创建新产品。我一直在使用的一种非常低效的方法是遍历json数组,对于每个productId,使用productRepository查找产品,然后逐个设置产品的shipmentDetail。我不确定这是否是最佳实践,因为我是自学成才

因此,在伪代码中,我试图做的是:

  • 接收JSON
  • 实例化装运实体
  • 实例化shipmentDetail实体的数组 对于每个装运细节: 1.查找具有给定productId的产品 2.使用产品和装运实例化shipmentDetail

  • 代码已经大大简化,以便更好地展示问题,

    我认为您当前的方法不是一个糟糕的解决方案,您正在正确地处理问题,并且只需几步

    无论如何,有一件事你可以尝试一下

    我们的想法是在支持与
    产品
    实体关系的同一数据库列上定义一个新字段
    productId
    ,类似于:

    @实体
    @表(name=“装运详情”)
    公共类ShipmentDetail实现可序列化{
    @身份证
    @GeneratedValue(策略=GenerationType.IDENTITY)
    @列(name=“Shipping\u DETAIL\u ID”,null=false)
    私有int-shipmentDetailId;
    @列(name=“PRODUCT\u ID”,null=false)
    私有字符串productId;
    @许多酮
    @JoinColumn(name=“PRODUCT_ID”,insertable=false,updateable=false)
    私人产品;
    @杰索尼奥雷
    @许多酮
    @JoinColumn(name=“shipping\u ID”,null=false)
    私人运输;
    //忽略了一堆其他变量
    公共船舶详情(){
    }
    公共装运详细信息(装运、产品){
    本产品=产品;
    本次装运=装运;
    }
    }
    
    product
    字段必须注释为not
    insertable
    和not
    updateable
    :相反,Hibernate会抱怨应该使用哪个字段来维护与
    product
    实体的关系,换句话说,就是维护实际列值

    修改与
    ShipmentDetail
    ShipmentDetail
    关系,并传播持久性操作(根据需要调整代码):

    @OneToMany(mappedBy=“shipping”,cascade=CascadeType.ALL,orphan=true)
    私有列表shipmentDetailList;
    
    然后,您可以安全地依赖Spring+Jackson反序列化,并获得对接收的
    装运
    对象的引用:

    public ResponseEntity processShipping(@RequestBody-shipping){
    //此时,装运应包含不同的细节,
    //每个都具有相应的productId信息
    //执行所需的验证,如有必要,记录信息
    //保存对象:它应该在数据库中保存整个对象树
    shipmentRepository.save(发货);
    }
    
    这种方法有一个明显的缺点,
    产品的存在事先没有检查

    虽然可以使用外键确保数据库级别的数据完整性,但在执行实际插入之前,验证信息是否正确可能会比较方便:

    public ResponseEntity processShipping(@RequestBody-shipping){
    //此时,装运应包含不同的细节,
    //每个都具有相应的productId信息
    //执行所需的验证,如有必要,记录信息
    List shipmentDetails=shipping.getShipmentDetails();
    if(shipmentDetails==null | | shipmentDetails.isEmpty()){
    //适当地处理错误
    抛出新的ResponseStatusException(HttpStatus.BAD_请求,“未提供装运详细信息”);
    }
    shipmentDetails.forEach(shipmentDetail->{
    斯特里
    
    public ResponseEntity<String> test2(@RequestBody String jsonString) throws JsonProcessingException {
        
        JsonNode wholeJson = objectMapper.readTree(jsonString);
        Shipment newShipment = objectMapper.treeToValue(wholeJson, Shipment.class);
        
        return new ResponseEntity<>("Transfer Shipment successfully created", HttpStatus.OK);
    }
    
    Product product = productRepository.findById(productId)
    
    public class ShipmentDeserializer extends JsonDeserializer {
         @Override
         public Shipment deserialize(JsonParser jp, DeserializationContext ctxt)
                 throws IOException, JsonProcessingException {
             JsonNode node = jp.getCodec().readTree(jp);
             String destination = node.get("destination").asText();
             Shipment shipment = new Shipment(destination);
             JsonNode shipmentDetailsNode = node.get("shipmentDetails");
             List shipmentDetailList = new ArrayList();
             for (int c = 0; c < shipmentDetailsNode.size(); c++) {
                 JsonNode productNode = shipmentDetailsNode.get(c);
                 String productId = productNode.get("productId").asText();
                 Product product = new Product(productId);
                 ShipmentDetail shipmentDetail = new ShipmentDetail(product);
                 shipmentDetailList.add(shipmentDetail);
             }
             shipment.setShipmentDetailList(shipmentDetailList);
             return shipment;
         }
     }
     @JsonDeserialize(using = ShipmentDeserializer .class)
     public class Shipment {
         // Class code
     }
    
     public ResponseEntity test2(@RequestBody String jsonString) throws JsonProcessingException {
         Shipment newShipment = objectMapper.readValue(jsonString, Shipment.class);
         /* More code */
         return new ResponseEntity("Transfer Shipment successfully created", HttpStatus.OK);
     }
     
    
     public ResponseEntity test2(@RequestBody String jsonString) throws JsonProcessingException {
         Shipment newShipment = objectMapper.readValue(jsonString, Shipment.class);
         shipmentRepository.save(newShipment);
         List<ShipmentDetail> shipmentDetails = newShipment.getShipmentDetailList();
         for (int i = 0; i < shipmentDetails.size(); c++) {
             ShipmentDetail shipmentDetail = shipmentDetails.get(i);
             shipmentDetail.setShipment(newShipment);
             Product product = productRepository.findById(productId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No product with ID of: " + productId + " exists!"));
             shipmentDetail.setProduct(product);
             shipmentDetailRepository.save(shipmentDetail);
         }
         return new ResponseEntity("Transfer Shipment successfully created", HttpStatus.OK);
     }
     
    public class ShipmentDeserializer extends JsonDeserializer {
            @Override
            public Shipment deserialize(JsonParser jp, DeserializationContext ctxt)
                    throws IOException, JsonProcessingException {
                JsonNode node = jp.getCodec().readTree(jp);
                String destination = node.get("destination").asText();
                Shipment shipment = new Shipment(destination);
                JsonNode shipmentDetailsNode = node.get("shipmentDetails");
                List shipmentDetailList = new ArrayList();
                for (int c = 0; c < shipmentDetailsNode.size(); c++) {
                    JsonNode productNode = shipmentDetailsNode.get(c);
                    String productId = productNode.get("productId").asText();
                    Product product = productRepository.findById(productId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No product with ID of: " + productId + " exists!"));
                    ShipmentDetail shipmentDetail = new ShipmentDetail(product);
                    shipmentDetailList.add(shipmentDetail);
                }
                shipment.setShipmentDetailList(shipmentDetailList);
                return shipment;
            }
        }