我有以下三个实体类:
发货实体:
@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 = "SHIPMENT_DETAIL")
public class ShipmentDetail implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "SHIPMENT_DETAIL_ID", nullable = false)
private int shipmentDetailId;
@ManyToOne
@JoinColumn(name = "PRODUCT_ID", nullable = false)
private Product product;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "SHIPMENT_ID", nullable = false)
private Shipment shipment;
//bunch of other variables omitted
public ShipmentDetail() {
}
public ShipmentDetail(Shipment shipment, Product product) {
this.product = product;
this.shipment = shipment;
}
产品实体:
@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反序列化一个新的发货,这个发货与已经存在的对象只有id的关系。我知道你可以简单地用objectmapper反序列化,但是这要求每个shipmentdetails中都有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<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);
}
我尝试了这个解决方案,但没有效果:用jackson引用现有对象反序列化
如何使产品实体搜索现有产品,而不是尝试创建新产品。我一直使用的一种非常低效的解决方法是遍历json数组,使用productrepository为每个productid找到产品,然后用产品逐个设置shipmentdetail。我不确定这是否是最好的做法,因为我自学 Spring 。
所以在伪代码中我想做的是:
接收json
示例化发货实体
为每个shipmentdetail示例化shipmentdetail实体的数组:1。查找具有给定productid 2的产品。用产品和装运示例化shipmentdetail
代码已经大大简化,以更好地展示问题,
2条答案
按热度按时间tct7dpnv1#
在这一部分中,您的代码有一个瓶颈:
因为您要对每个productid进行查询,而且它在处理大量产品时的性能会很差。忽略这一点,我将推荐这种方法。
构建您自己的反序列化程序(请参见以下内容):
将反序列化程序添加到装运类:
反序列化字符串:
此时,您只需要将json转换为类,因此我们需要持久化数据。
我知道您希望减少测试方法中的代码,但我不建议将json反序列化与持久层结合起来。但是如果您希望遵循该路径,可以将productrepository.findbyid(productid)移动到shipmentdeserializer类中,如下所示:
但是如果您想这样做,您需要将存储库注入到反序列化程序中(请参见此图)。
new9mtju2#
我认为你目前的方法不是一个坏的解决办法,你正在正确地处理问题,而且只需几步。
不管怎样,你可以尝试以下方法。
这个想法将提供一个新的领域,
productId
,在支持与的关系的同一数据库列上定义Product
实体,类似于:这个
product
字段必须注解为notinsertable
而不是updatable
:相反,hibernate会抱怨应该使用哪个字段来维护与的关系Product
实体,换句话说,保持实际的列值。修改
Shipment
与…的关系ShipmentDetail
以及传播持久性操作(根据需要调整代码):然后,您可以安全地依赖spring+jackson反序列化并获得对接收到的
Shipment
对象:这种方法有一个明显的缺点,即
Product
没有事先检查。尽管您可以使用外键确保数据库级别的数据完整性,但在执行实际插入之前验证信息是否正确可能会很方便: