Spring Boot JPA更新含null值的数据库列 嵌入类字段更新报错如何解决
问题排查结果
核心原因
你遇到的是NullPointerException,报错点为你标粗的代码行_users.getTransferDetails().setTransferCurrency(users.getTransferDetails().getTransferCurrency()),触发原因是:
当你从数据库查询得到_users对象时,如果该条数据中TransferDetails对应的所有数据库列均为null,JPA默认会将实体类中的transferDetails字段直接映射为null,而非实例化一个空的TransferDetails对象,你直接对null值调用set方法就会触发空指针。同理beneficiaryDetails字段也存在相同的问题。
修复方案
方案1:更新时判空后再赋值
在更新嵌入类字段前先判断是否为null,为空则先实例化再赋值,代码修改如下:
// 处理TransferDetails字段 if (users.getTransferDetails() != null) { TransferDetails existTransfer = _users.getTransferDetails(); // 原有嵌入类为null则先初始化 if (existTransfer == null) { existTransfer = new TransferDetails(); _users.setTransferDetails(existTransfer); } existTransfer.setTransferCurrency(users.getTransferDetails().getTransferCurrency()); existTransfer.setChequeCurrency(users.getTransferDetails().getChequeCurrency()); } // 处理BeneficiaryDetails字段 if (users.getBeneficiaryDetails() != null) { BeneficiaryDetails existBeneficiary = _users.getBeneficiaryDetails(); if (existBeneficiary == null) { existBeneficiary = new BeneficiaryDetails(); _users.setBeneficiaryDetails(existBeneficiary); } existBeneficiary.setBeneficiaryName(users.getBeneficiaryDetails().getBeneficiaryName()); }
方案2:实体类嵌入字段初始化默认值
直接在Users实体类中对嵌入类字段初始化空实例,避免查询得到null值:
@Entity @Data public class Users extends AbstractEntity { private String name; private String email; private Audit audit = new Audit(); private TransferDetails transferDetails = new TransferDetails(); private BeneficiaryDetails beneficiaryDetails = new BeneficiaryDetails(); }
方案3:开启Hibernate空嵌入类自动实例化配置
如果使用Hibernate作为JPA实现,可在application.properties/application.yml中添加以下配置,开启后当嵌入类所有字段为null时,Hibernate会自动实例化空对象,不会返回null:
spring.jpa.properties.hibernate.create_empty_composites.enabled=true
额外优化建议
- 嵌入类的字段名建议遵循Java驼峰命名规范,首字母小写,仅通过
@Column(name="xxx")指定数据库列名即可,避免框架反射调用get/set方法时出现字段匹配异常。 - 事务注解建议迁移到业务Service层,Controller层仅做参数校验、请求转发和响应封装,更符合分层规范。
- 异常捕获时建议直接打印完整异常栈
LOGGER.error("更新失败", e),无需手动拼接栈信息,更便于排查问题。
内容的提问来源于stack exchange,提问作者Tabish Hafeez
相关产品推荐
相关产品推荐

