JPA子实体@ManyToOne关联父实体属性始终为null如何解决
问题根源
这是双向@OneToMany关联的常见问题,核心原因有两个:
- 你给
@OneToMany添加了mappedBy = "compania"属性,代表外键关联完全由Office类的compania字段维护,只有Office对象的compania属性有值时,JPA才会给office表的compania_id外键字段赋值。你现在保存Compania时仅填充了Compania的office列表,没有给每个Office对象设置所属的Compania,导致数据库中office表的compania_id本身就是空值,查询时compania字段自然为null,对应的JPQL条件查询也不会返回结果。 - 存量数据受之前的关联配置影响,
compania_id字段没有值,也会导致查询为空。
解决步骤
1. 修正保存逻辑,主动维护双向关联
在保存Compania之前,遍历关联的Office列表,给每个Office手动设置所属的Compania,修改你的postCompania方法:
public void postCompania(Compania compania) { if (compania.getId() != null) { if (companiaRepository.existsById(compania.getId())) { throw new IllegalStateException( "Compañia con id " + compania.getId() + " ya existe" ); } } // 新增双向关联维护逻辑 if (compania.getOffice() != null) { compania.getOffice().forEach(office -> office.setCompania(compania)); } companiaRepository.save(compania); }
2. 优化查询逻辑(可选)
你当前的getChilds查询语法本身没有问题,如果你希望查询结果直接携带compania数据,避免懒加载问题,可以调整JPQL添加fetch join:
@Query("select o from Office o left join fetch o.compania where o.compania.id = :companiaId and lower(o.title) like lower(concat('%', :title, '%') ) ") List<Office> getChilds(@Param("companiaId") Long companiaId, @Param("title")String title);
3. 解决序列化循环引用问题(可选)
双向关联后直接返回实体给前端会出现循环序列化问题,可以在Office的compania字段上添加@JsonIgnoreProperties("office")注解,既可以正常返回compania基础信息,也不会出现循环引用报错:
@ManyToOne @JsonIgnoreProperties("office") private Compania compania;
修改完成后重新插入测试数据即可验证效果,存量历史数据需要手动补全office表的compania_id字段值。
内容的提问来源于stack exchange,提问作者Varox
相关产品推荐
相关产品推荐

