You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承实体一对一关联配置问题:关联对象为空的解决

问题原因

你的问题出在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 22:10:28