Hibernate数据类布尔属性isPrimary无法单独更新至数据库的问题
问题:Hibernate仅更新嵌套类布尔属性时数据库未同步的原因与解决方法
我在项目中使用Hibernate数据类结合DAO实现数据保存与更新,需要将嵌套类Address中的布尔属性isPrimary更新至my_class数据库表中。
实体类代码
@Entity @Table(name = "my_class") public class MyClassData { private String id; private String name; private Address address; // getter, setter } class Address { private String street; private boolean isPrimary; // getter, setter }
异常场景
- 仅更新
isPrimary时,数据库未同步:
MyClassData myClassData = myclassDAO.getById(id); myClassData.getAddress().setIsPrimary(false); myclassDAO.update(myClassData); // 数据库无更新
- 同时更新
name与isPrimary时,两个属性均成功更新:
MyClassData myClassData = myclassDAO.getById(id); myClassData.setName("John"); myClassData.getAddress().setIsPrimary(false); myclassDAO.update(myClassData); // 两个值均同步到数据库
原因分析
- Hibernate的脏检查机制默认仅追踪实体本身的属性变化,对于未标记为嵌入式的普通嵌套POJO(比如这里的
Address),Hibernate无法感知其内部属性的修改。 - 当修改主实体
MyClassData的name属性时,Hibernate检测到主实体变化,会触发整个实体的更新操作,此时嵌套类Address的所有属性会被一并同步;但仅修改Address内部的isPrimary时,Hibernate认为主实体无变化,不会执行更新语句。
解决方法
方法一:将Address标记为嵌入式类(推荐)
给Address添加@Embeddable注解,同时在MyClassData的address字段上添加@Embedded注解,让Hibernate识别这是嵌入式对象,从而追踪其内部属性变化:
@Embeddable class Address { private String street; private boolean isPrimary; // getter, setter } @Entity @Table(name = "my_class") public class MyClassData { private String id; private String name; @Embedded private Address address; // getter, setter }
方法二:手动触发脏检查
修改Address属性后,手动将MyClassData标记为脏数据,强制Hibernate执行更新:
MyClassData myClassData = myclassDAO.getById(id); myClassData.getAddress().setIsPrimary(false); // 获取Hibernate Session,标记实体为脏 Session session = entityManager.unwrap(Session.class); session.setDirty(myClassData); myclassDAO.update(myClassData);
方法三:重新赋值Address对象
修改isPrimary后,重新给MyClassData的address字段赋值,让Hibernate感知到实体属性变化:
MyClassData myClassData = myclassDAO.getById(id); Address address = myClassData.getAddress(); address.setIsPrimary(false); myClassData.setAddress(address); // 重新赋值触发脏检查 myclassDAO.update(myClassData);
内容的提问来源于stack exchange,提问作者Shelomi Silva
相关产品推荐
相关产品推荐

