@ManyToOne 如何让 Json 引用现有的外键?

问题描述 投票:0回答:2

我正在制作一个 Spring Boot RESTful 应用程序。我有两个实体: 访客:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private String email;
    private String gender;
}

和产品

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private int qty;
    private int price;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "customer_id", referencedColumnName = "id")
    private Customer customer;
}

这就是我尝试通过控制器将 Json 推入 OrderRequest 对象的方式:

@PostMapping("/placeOrder")
    public Product saveOrder(@RequestBody OrderRequest request){
       return productRepository.save(request.getProduct());
    }

订单请求类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderRequest {

    private Product product;
}

存储库类是标准的:

public interface ProductRepository extends JpaRepository<Product, Integer> {}
public interface CustomerRepository extends JpaRepository<Customer, Integer> {}

我希望 json 看起来像这样:

{
   "product":{
       "name":"Mobile",
       "price":10000,
        "qty":1,
        "idCustomer": 1
   }
}

问题:如何才能在 Customer 表中已有行的情况下,将 Json 发送到服务器,其中我仅指示产品参数和一个外键参数(该参数将是对 Customer 行的引用)? ?谢谢

hibernate rest spring-data-jpa spring-rest
2个回答
0
投票

在控制器层公开持久层实体并不是最佳实践,因为您的 API 会与数据的内部表示耦合。

实现您的需求的常见方法是使用传输对象模式。也就是说,创建单独的类以在 API 中使用。在您的用例中,您可以创建具有以下结构的 ProductTO 类:

public class ProductTO {
    private int id;
    private String name;
    private int qty;
    private int price;

    private int customerId;
}

然后您可以手动映射 ProductTO 和 Product 之间的字段,或者使用任何映射库(例如:MapStruct)自动复制两个类中同名字段的值。

外键应手动分配:

Customer customer = this.customerRepo.findById(productTO.getCustomerId()).orElseThrow(() -> new YourException());
product.setCustomer(customer);

0
投票

您可以将您的产品实体类更改为这样

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private int qty;
    private int price;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "customer_id", referencedColumnName = "id")
    private Customer customer;

    // --------------------------------------------
    // Add this property to display the customer ID
    @Column(name = "customer_id", insertable = false, updatable = false)
    private Long idCustomer;

    public Long getIdCustomer() {
         return this.idCustomer;
    }
    // --------------------------------------------
}

请注意,“customer_id”应该已经存在于您的“Product”表中,并且您需要在列注释中添加insertable = false,updatable = false以表明其仅供阅读。

尝试此解决方案,如果您将来遇到任何问题,那么您需要创建另一个仅用于显示的实体调用模型。

© www.soinside.com 2019 - 2024. All rights reserved.