我最近开始使用 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值?
答案 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对象映射到我的实体有疑问。