代码之家  ›  专栏  ›  技术社区  ›  HoosierDude

Spring CrudRepository save是否排除JSON中的子实体?

  •  0
  • HoosierDude  · 技术社区  · 7 年前

    我有一个SpringBoot应用程序,正在使用CrudRepository将对象持久化到DB。我有一个产品实体类,它与供应商实体具有多对一关系。我传递的JSON包含产品和嵌入式供应商的详细信息,但我最终只想传递产品详细信息并包含供应商ID。有什么注释可以帮我解决这个问题吗?

    这是我的代码:

    @Entity
    public class Product {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
        @ManyToOne
        @JoinColumn(name="VendorID")
        private Vendor vendor;
        @Column(name="partnumber")
        @JsonProperty("PartNumber")
        private String vendorPartNumber;
        @JsonProperty("Name")
        private String name;
    
    @Entity
    public class Vendor {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @JsonProperty("Code")
    private String code;
    @JsonProperty("Name")
    private String name;
    ....
    @OneToMany(mappedBy = "vendor", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JsonIgnore
    private List<Product> products;
    

    我传递的JSON(有效)如下所示:

        {
        "Vendor": {
            "Id":1,
            "Code": "BB-1001",
            "Name": "Best Buy",
            "Address": "100 Best Buy Street",
            "City": "Louisville",
            "State": "KY",
            "Zip": "40207",
            "Phone": "502-111-9099",
            "Email": "geeksquad@bestbuy.com",
            "IsPreApproved": "false"
        },
        "PartNumber":"TEST01",
        "Name":"Test Product 01",
        "Price":99.99
    }
    

    我最终希望删除对vendor的JSON对象引用,并替换为VendorId。

    3 回复  |  直到 7 年前
        1
  •  0
  •   Sync    7 年前

    按注释的解决方案

    您可以使用 @JsonSerialize 提供自定义序列化以实现所需的内容。

    @Entity
    public class Product {
    
        ...
    
        @JsonSerialize(using = VendorToIdSerializer.class)
        @ManyToOne
        @JoinColumn(name="VendorID")
        private Vendor vendor;
    
        ...
    }
    
    public class VendorToIdSerializer extends JsonSerializer<Vendor> {
    
        @Override
        public void serialize(Vendor vendor, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
            String vendorIdAsString = String.valueOf(vendor.getId());
            jsonGenerator.writeObject(vendorIdAsString);
        }
    }
    

    DTO解决方案

    然而,正如其他人所指出的,更干净的方法是创建一个DTO类,该类充当 Product .

    public class ProductView {
    
        private final int vendor;
        ...
    
        public ProductView(Vendor vendor) {
            this.vendor = vendor.getId();
            ...
        }
    
        // getters
    }
    
        2
  •  0
  •   HoosierDude    7 年前

    我的问题通过使用@JsonBackReference和@JsonManagedReference注释得到了解答。不过,我将继续研究上面建议的DTO。谢谢大家!

        3
  •  0
  •   Vlad Mihalcea    7 年前

    我还建议创建一个符合您需要的DTO。

    使用JPA,您可以使用构造函数表达式创建DTO实例:

    下面是弗拉德·米哈尔恰(VladMihalcea)写的一篇伟大文章中的一个例子 https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/

    List<PostDTO> postDTOs = entityManager.createQuery(
        "select new " +
        "   com.vladmihalcea.book.hpjp.hibernate.query.dto.projection.jpa.PostDTO(" +
        "       p.id, " +
        "       p.title " +
        "   ) " +
        "from Post p " +
        "where p.createdOn > :fromTimestamp", PostDTO.class)
        .setParameter( "fromTimestamp", Timestamp.from(LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )
            .toInstant( ZoneOffset.UTC ) ))
        .getResultList();