Spring CrudRepository保存在JSON中排除子实体?

时间:2017-12-13 12:50:44

标签: json spring spring-data-jpa

我有一个SpringBoot应用程序,并使用CrudRepository将对象持久保存到数据库。我有一个Product实体类,它与Vendor实体有多对一的关系。我传递的JSON包含产品和嵌入式供应商的详细信息,但我最终只想传递产品详细信息并包含vendorID。是否有一些注释可以解决这个问题?

这是我的代码:

@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
}

我最终想删除对供应商的JSON对象引用,并用VendorId替换。

3 个答案:

答案 0 :(得分:0)

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

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

这是Vlad Mihalcea撰写的一篇精彩文章的例子 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();

答案 1 :(得分:0)

注释解决方案

您可以使用@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)

使用@JsonBackReference和@JsonManagedReference注释回答了我的问题。我将按照上面的建议继续研究DTO。感谢您!