继承实体一对一关联配置问题:关联对象为空的解决
你的问题出在OneToOne关系的维护端设置错误。在ShapeDetailsEntity中使用mappedBy = "shapeDetailsEntity",说明ShapeEntity是这个一对一关系的拥有端(Owning Side),数据库中的外键字段会存储在ShapeEntity对应的表中,指向ShapeDetailsEntity的ID。
目前你只在ShapeDetailsEntity中设置了关联的shapeEntity,但没有更新ShapeEntity中的shapeDetailsEntity字段。由于拥有端负责维护外键关系,这就导致ShapeEntity表中的外键字段始终为null,进而调用shapeEntity.getShapeDetailsEntity()时出现空指针异常。
1. 双向绑定关联关系并更新拥有端
修改createShapeDetails方法,在创建ShapeDetailsEntity后,同时将其绑定到ShapeEntity上,并保存ShapeEntity以更新外键:
public ShapeDetailsEntity createShapeDetails(ShapeEntity shapeEntity) { ShapeDetailsEntity shapeDetailsEntity = new ShapeDetailsEntity(); // 绑定反向关联 shapeDetailsEntity.setShapeEntity(shapeEntity); // 绑定拥有端关联(关键步骤) shapeEntity.setShapeDetailsEntity(shapeDetailsEntity); // 先保存详情实体(生成ID) shapeDetailsEntity = shapeDetailsEntityRepository.saveAndFlush(shapeDetailsEntity); // 保存形状实体,更新外键字段 switch (shapeEntity.getClass().getSimpleName()) { case "CircleEntity": circleEntityRepository.saveAndFlush((CircleEntity) shapeEntity); break; case "SquareEntity": squareEntityRepository.saveAndFlush((SquareEntity) shapeEntity); break; case "RectangleEntity": rectangleEntityRepository.saveAndFlush((RectangleEntity) shapeEntity); break; default: throw new IllegalArgumentException(); } return shapeDetailsEntity; }
2. 优化:为拥有端添加级联操作(可选)
如果希望通过保存ShapeEntity自动完成ShapeDetailsEntity的持久化,可以在ShapeEntity的shapeDetailsEntity字段上添加cascade = CascadeType.ALL:
@Entity @Inheritance(strategy = TABLE_PER_CLASS) @Getter @Setter @NoArgsConstructor public abstract class ShapeEntity { // ... 其他字段 @OneToOne(cascade = CascadeType.ALL) // 添加级联配置 private ShapeDetailsEntity shapeDetailsEntity; // ... 抽象方法 }
此时createShapeDetails方法可以简化为:
public ShapeDetailsEntity createShapeDetails(ShapeEntity shapeEntity) { ShapeDetailsEntity shapeDetailsEntity = new ShapeDetailsEntity(); shapeDetailsEntity.setShapeEntity(shapeEntity); shapeEntity.setShapeDetailsEntity(shapeDetailsEntity); // 只需要保存ShapeEntity,级联操作会自动保存ShapeDetailsEntity switch (shapeEntity.getClass().getSimpleName()) { case "CircleEntity": circleEntityRepository.saveAndFlush((CircleEntity) shapeEntity); break; case "SquareEntity": squareEntityRepository.saveAndFlush((SquareEntity) shapeEntity); break; case "RectangleEntity": rectangleEntityRepository.saveAndFlush((RectangleEntity) shapeEntity); break; default: throw new IllegalArgumentException(); } return shapeDetailsEntity; }
3. 验证结果
修改后,再次调用shapeEntity.getShapeDetailsEntity()时就不会出现空指针,同时数据库中ShapeEntity表对应的外键字段也会正确存储ShapeDetailsEntity的ID。
内容的提问来源于stack exchange,提问作者Lulex97

