首页 > 解决方案 > 如何在@ManyToOne 单向映射中使用spring boot 保存包含子对象的父对象?

问题描述

我是春季靴子的新手。我有两个模型类 Party(parent) 和 PartyCategory(child)。PartyCategory 成功存储数据 id、labelAr 和 labelEn。

现在我在 json 请求中传递子 ID,并在 json 响应中获取 labelAr 和 labelEn 的空值,如下所示。有人可以帮助这里做什么和做错了吗。

我也粘贴了我的代码。

json请求:

{

    "name": "Party A",
    "description": "Description of Party A",
    "category": {
        "id": 1
    }
}

json响应;

{
    "id": 6,
    "name": "Party A",
    "description": "Description of Party A",
    "category": {
        "id": 1,
        "labelAr": null,
        "labelEn": null
    }
}

派对.java:

   public class Party {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer id;
        private String name;
        private String description;
        @ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
        @JoinColumn(name = "category_id")
        private PartyCategory category;

        ....setters and getters
   }

PartyCategory.java:-

public class PartyCategory {

    @Id
    @GeneratedValue
    private Integer id;
    private String labelAr;
    private String labelEn;

    ...setters and getters..

存储库:

public interface PartyCategoryRepository extends JpaRepository<PartyCategory, Integer> {

}

public interface PartyRepository extends JpaRepository<Party, Integer> {

}

服务:

public class PartyServiceImpl {
    @Autowired
    PartyRepository partyRepository;

public Party saveParty(Party party) {

        return partyRepository.save(party);
    }

控制器:

@RestController
public class PartyController {

    @Autowired
    PartyServiceImpl partyServiceIml;


    @PostMapping(value = "/party/save")
    public Party saveParty(@RequestBody Party party ) {
        Party returnedParty = partyServiceIml.saveParty(party);
        return returnedParty;
    }
}

标签: restspring-bootspring-mvcspring-data-jpajackson

解决方案


问题是您发布的类别未被识别为现有类别。

然后,您可以执行以下操作。首先,创建一个 Jackson 转换器类来自定义 Json 反序列化。我不确定这些是否是 Spring 管理的,但它们是这样的,因此您可以注入必要的存储库。

import com.fasterxml.jackson.databind.util.StdConverter;

@Component
public class CategoryConverter extends StdConverter<Integer, PartyCategory> {

    @Autowired
    private PartyCategoryRepository repo;

    @Override
    public PartyCategory convert(Integer value) {
        return repo.findById(value).get();
    }
}

然后按如下方式更新您的实体,以便category通过上面创建的转换器处理 Json 属性。请注意,实际上我会使用 Jackson 混合来应用此自定义反序列化器,因为这将避免使用 Json 处理指令“污染”实体类。你可以看看如何做到这一点。

@Entity
public class Party {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    private String description;

    @ManyToOne
    @JoinColumn(name = "category_id")
    @JsonDeserialize(converter = CategoryConverter.class) //in real life use a 'mix-in'
    private PartyCategory category;
}

然后你可以如下发布 JSON,我们只需指定现有类别的 id:

{

    "name": "Party A",
    "description": "Description of Party A",
    "category": 1
}

通过增强此解决方案以按照建议使用混入,然后可以将视图模型与实体模型干净地分开,而无需创建通常会在很大程度上复制实体模型并且需要繁琐的映射代码来处理的 DTO 层转换。


推荐阅读