我正在使用 JPA 注释学习 hibernate 的基础知识,我有一个问题。我创建了一个虚拟项目,其结构如下 -
一个实体类人
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="personIdGenerator")
private int personIdentifier;
private String firstName;
private String lastName;
private String title;
private String sex;
@ElementCollection(fetch=FetchType.LAZY)
@MapKeyEnumerated(EnumType.STRING)
@javax.persistence.MapKeyColumn(name="ADDRESS_TYPE")
private Map<AddressType,Address> address = new HashMap<AddressType, Address>();
一个可嵌入类地址 -
private String streetAddressLane1;
private String streetAddressLane2;
private String streetAddressLane3;
@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY)
private City city;
最后一个实体类 City -
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int cityId;
private String city;
private String state;
private String country;
private String zipCode;
现在我有一个主要方法,代码为 -
SessionFactory sesFac = new Configuration().configure().buildSessionFactory();
Session session = sesFac.openSession();
Transaction tx = session.beginTransaction();
// session.save(city);
//session.save(adr);
Person person = (Person) session.get(Person.class, 101);
//Employee empNew = (Employee)session.merge(emp);
//empNew.setEmpId(2);
// System.out.println(person.getAddress().get(AddressType.HOME_ADDRESS).getCity().getZipCode());
//Employee empOld= (Employee) session.get(Employee.class, empNew.getEmpId());
session.getTransaction().commit();
session.flush();
session.close();
session = sesFac.openSession();
tx = session.beginTransaction();
// session.save(city);
//session.save(adr);
person.setLastName("gggggg");
session.saveOrUpdate(person);
//Employee empNew = (Employee)session.merge(emp);
//empNew.setEmpId(2);
//Employee empOld= (Employee) session.get(Employee.class, empNew.getEmpId());
session.getTransaction().commit();
session.close();
在主要方法中,我得到两个不同的 session 和两个不同的事务。在第一个事务中,我获得了 ID 为 101 的人的记录,该记录已存在于数据库中,在第二个事务中,我将姓氏设置为 gggggg。
现在,由于我使用延迟初始化,因此当我尝试更改名称并将其传递给 saveOrUpdate 方法时,不应该有任何地址和城市。因此,这应该删除分配给人员 ID 101 的现有地址,但事实并非如此。地址仍然存在,姓氏已更改为 ggggg。我无法理解这可能是什么原因。 Hibernate 创建的代理是否处理此类更新或什么?
最佳答案
“未加载”与“已删除”不同,Hibernate 会跟踪它加载的所有内容的差异。
在这种特定情况下,当 Hibernate 加载 Person
实体时,它将 address
字段包装在 PersistentMap
中。 ,最初被标记为尚未加载。如果您要访问address
字段并读取或更改其中的任何内容,PersistentMap
将从当时的数据库加载其内容,并跟踪某些内容发生了更改。然后 Hibernate 将在提交时保存更改。
由于您不读取或更改 address
字段,因此当 Hibernate 处理提交时,它会检查 PersistentMap
,发现它从未加载,然后继续忽略它,留下该部分数据不变。
如果您想清除地址
数据,则需要明确执行此操作。 Hibernate 试图避免对数据的意外更改,并且将从未加载的内容视为删除将很容易发生意外。
关于java - 为什么 hibernate 不删除行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36251251/