为什么Spring Boot休眠的OneToMany映射子级返回空值?

时间:2019-12-10 12:11:39

标签: java spring hibernate spring-boot

我最近开始使用 Spring Boot Hibernate 。我只是尝试实现两个实体之间的第一个映射。

但是我不太了解不同的映射注释是如何工作的。尝试将Entity持久化到数据库中时,我得到null值。

我有一个Institution实体,可以包含许多Department实体(OneToMany),还有一个Department实体,它与一个Institution实体(ManyToOne)相关。 / p>

这是我的机构实体

@Entity
@NoArgsConstructor
@Setter
@Getter
@Table(name = "institution")
public class Institution {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(name = "id", columnDefinition = "BINARY(16)")
    private UUID id;

    @Column(name = "name")
    private String name;

    @Column(name = "acronym")
    private String acronym;

    @OneToMany( mappedBy = "institution")
    List<Department> departments;
}

部门实体

@Entity
@NoArgsConstructor
@Getter
@Setter
@Table(name = "department")
public class Department {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(name = "id", columnDefinition = "BINARY(16)")
    private UUID id;

    @Column(name = "name")
    private String name;

    @ManyToOne
    @JoinColumn(name = "institution_id")
    private Institution institution;
}

InstitutionService

@Slf4j
@Service
@AllArgsConstructor
public class InstitutionService {

    private final Logger logger = LoggerFactory.getLogger(InstitutionService.class);
    private final InfoMessages infoMessages = new InfoMessages();

    private final InstitutionRepository institutionRepository;

    public Institution addInstitution(Institution institution) {
        return institutionRepository.save(institution);
    }

    public Optional<Institution> getInstitutionById(UUID id) {
        return institutionRepository.findById(id);
    }

    public List<Institution> getInstitutions(String searchParam) {

        if (searchParam != null) {

            return institutionRepository.findInstitutionByAcronymContainingOrNameContainingIgnoreCase(searchParam, searchParam);
        }

        return institutionRepository.findAll();
    }

    public Institution getInstitutionByName(String name){
        return institutionRepository.findInstitutionByName(name);
    }
}

InstitutionController

@AllArgsConstructor
@Api(value = "/institution", tags = "Institution Management System")
@RequestMapping(
    path = "/institution",
    produces = MediaType.APPLICATION_JSON_VALUE)
@RestController
public class InstitutionController {

    private final InstitutionService institutionService;

     @ApiOperation("Add institution")
    @PostMapping(consumes = ("application/json"))
    public ResponseEntity<WrappedResponse<Institution>> createInstitution(
        @ApiParam("JSON Object representing Institution")
        @RequestBody Institution institution
    ) {

        institutionService.addInstitution(institution);

        WrappedResponse<Institution> wrappedResponse = new WrappedResponse<>();
        wrappedResponse.setList(Collections.singletonList(institution));

        return ResponseEntity
            .status(HttpStatus.CREATED)
            .location(URI.create("/institution/" + institution.getId()))
            .body(
                wrappedResponse
            );
    }

}

这是我的输入

{
  "acronym": "uio",
  "departments": [
    {
      "name": "Biology"
    }
  ],
  "name": "University of Oslo"
}

这是我尝试发布机构实体时返回的JSON有效载荷

{
  "list": [
    {
      "id": "2163ff6a-71f4-40f7-bec2-dfeadbcdfec8",
      "name": "University of Oslo",
      "acronym": "uio",
      "departments": [
        {
          "id": null,
          "name": "Biology",
          "institution": null
        }
      ]
    }
  ]
}

为什么我要获得null的部门ID和机构ID值?

2 个答案:

答案 0 :(得分:2)

  

为什么我获得的部门ID为空值

因为您尚未在OneToMany上指定任何级联。因此,坚持一个机构就是这样做的:坚持该机构。如果还希望保留其包含的功能,则PERSIST操作(至少)需要to be cascaded。由于部门不存在,因此不会为其生成ID。

  

为什么我得到的机构ID为空值

由于您要保存的部门的institution字段为空。 因此在JSON中也为null。即使使用适当的级联,您在数据库中仍将获得空department.institution_id。您需要添加代码以初始化关联的这一方面,而这在输入JSON中不存在。

但是请注意,如果它不为null,则由于您尝试将循环数据结构序列化为JSON,因此会出现堆栈溢出错误。我强烈建议不要在控制器中接受和返回JPA实体。这些代表应用程序的持久状态。在设计API时,请明确指定要接收和返回的JSON,并设计代表该JSON的类。 JSON文档是一棵树。它不能是循环数据结构。

答案 1 :(得分:0)

我在here

中找到了解决该问题的方法

很显然,我对杰克逊(Jackson)以及它如何将JSON对象映射到我的实体有疑问。