Rest 如何在@manytone单向映射中使用spring boot保存包含子对象的父对象?

Rest 如何在@manytone单向映射中使用spring boot保存包含子对象的父对象?,rest,spring-boot,spring-mvc,spring-data-jpa,jackson,Rest,Spring Boot,Spring Mvc,Spring Data Jpa,Jackson,我是新来的春天靴子。我有两个模型类Party(家长)和PartyCategory(孩子)。PartyCategory成功存储数据id、labelAr和labelEn 现在我在json请求中传递子id,并在json响应中获取labelAr和labelEn的空值,如下所示。有人能帮我做点什么吗 我也粘贴了我的代码 Json请求: { "name": "Party A", "description": "Description of Party A", "category":

我是新来的春天靴子。我有两个模型类Party(家长)和PartyCategory(孩子)。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
    }
}
Party.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> {

}
控制器:

@RestController
public class PartyController {

    @Autowired
    PartyServiceImpl partyServiceIml;


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

首先,对数据库和rest服务使用相同的实体不是一个好的做法。它们应该是独立的实体,通常rest服务的实体称为DTO(数据访问对象)

现在,关于您的问题,代码中发生的事情是正常的,因为在保存新参与方时,您使用空值覆盖与ID 1关联的PartyCategory labelAr和labelEn,因为您没有为这两个标签提供任何值

return partyRepository.save(party);
如果要避免此问题,必须首先从数据库检索PartyCategory数据,设置为Party实体,然后将其保存到数据库。大概是这样的:

public class PartyServiceImpl {
    @Autowired
    PartyRepository partyRepository;

    @Autowired
    PartyCategoryRepository partyCategoryRepository;

    public Party saveParty(Party party) {
        PartyCategory partyCategory = partyCategoryRepository.findById(party.getPartyCategory().getId());

        party.setPartyCategory(partyCategory);

        return partyRepository.save(party);
    }

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

然后,您可以执行以下操作。首先,创建一个Jackson converter类来定制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();
    }
}
然后您可以发布JSON,如下所示,我们只需指定现有类别的id即可:

{

    "name": "Party A",
    "description": "Description of Party A",
    "category": 1
}
通过按照建议增强此解决方案以使用mix-ins,可以将视图模型与实体模型清晰地分离,而无需创建DTO层,DTO层通常会在很大程度上复制实体模型,并且需要繁琐的映射代码来处理转换

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

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