为什么hibernate没有删除行?

时间:2016-03-27 18:50:33

标签: java hibernate

我正在使用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;

最后是一个实体类城市 -

@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();

在主要方法中,我得到两个不同的会话和两个不同的事务。在第一个我得到人员ID 101的记录,这已经存在于数据库中,在第二个事务中,我将姓氏设置为gggggg。

现在因为我正在使用延迟初始化,所以当我尝试更改名称并将其传递给saveOrUpdate方法时,不应该有任何地址和城市。因此,这应该删除分配给人员ID 101的现有地址,但事实并非如此。地址仍在那里,姓氏正在改为ggggg。我无法理解这可能是什么原因。 hibernate创建的代理是否处理这种更新或什么?

2 个答案:

答案 0 :(得分:1)

&#34;未加载&#34;与&#34;删除&#34;不同,Hibernate跟踪它加载的所有内容的差异。

在这种特定情况下,当Hibernate加载Person实体时,它会将address字段包装在PersistentMap中,该字段最初被标记为尚未加载。如果您要访问address字段并读取或更改其中的任何内容,PersistentMap将在当时从数据库加载其内容,并跟踪某些内容已更改。然后,Hibernate会在提交时保存更改。

当你没有读取或更改address字段时,当Hibernate处理提交时,它会检查PersistentMap,发现它从未被加载,并继续忽略它,使数据部分保持不变

如果要清除address数据,则需要明确这样做。 Hibernate试图避免数据的意外更改,并且处理从未加载与删除相同的内容将非常容易发生事故。

答案 1 :(得分:0)

如果关闭会话,则会分离Person实体。当你调用saveOrUpdate()时,hibernate会将分离的对象重新附加到新的Session中。

为了执行延迟加载,Hibernate将Person包装在扩展Person的代理类中。初始化检查在此代理中完成。这意味着如果您从未在第一个会话中访问数据库中的地址,则代理将知道这一点,并且当实体在第二个会话中重新附加时,它会将地址视为未初始化而不是从数据库中删除它们。