Hibernate 数据的保存,更新和删除

数据的保存,更新和删除:
   1Session.save()方法:
Session.save()方法用于实体对象的持久化保存,也就是说当执行session.save()方法时会生成对应的insert SQL语句,完成数据的保存。如下面的代码:
User user=new User();
user.setName(“zx”);
Transaction tx=session.beginTransaction();
session.save(user);
tx.commit();
当执行到session.save()方法时,Hibernate并不会马上生成insert SQL语句来进行数据的保存,而是当稍后清理session的缓存时才有可能执行insert SQL语句,那么session.save()方法到底会执行哪些步骤呢?请看进行了如下总结:
一、           session的内部缓存中寻找保存对象,如果找到了,则认为此数据已经保存(曾经执行过insert操作),实体对象已经处于persistent状态,直接返回。此时即使数据相比之前的状态发生了变化,也将在事务提交时由脏数据检查来判定是否需要执行update操作。
二、            如果实体对象实现了 lifecycle 接口,那么将执行待保存对象的 onSave() 方法。
三、            如果实体对象实现了 Validatable 接口,那么将会执行相应的 validate() 方法。
四、            如果存在拦截器对象,那么将会执行 Interceptor.onSave() 方法。
五、            构造 insert SQL 语句完成数据保存。
六、            数据保存成功后,设定实体对象的 id 为插入记录的 id
七、            将保存后的实体对象纳入 Hibernate 的内部缓存(一级缓存)。注意 Hibernate 不会把保存后的实体对象纳入二级缓存,因为刚刚保存过的实体对象很可能在之后被修改,缓存的频繁更新以及带来的同步问题代价,超出了缓存该对象所带来的收益。
八、            最后如果该对象有关联对象,那么将会递归处理该级联对象。
 
1、       Session.update() 方法:
   前面我在实体对象状态转化部分曾经讲过, session.update() 方法能够将一个处于游离状态的对象,重新纳入 Hibernate 的内部缓存,变成持久化对象。如下面的代码:
Configuration cfg = new Configuration();
SessionFactory sf=cfg.  configure().buildSessionFactory();
Customer customer=new Customer(“zx”,27,images);// customer 对象处于自由状态
Session session=sf.openSession();
 
Transaction tx=session.beginTransaction();
session.save(customer);// 保存后 customer 对象处于持久化状态
session.flush();// 清空缓存后 customer 对象处于游离状态
tx.commit();
session.close();
 
Session session2=sf.openSession();
Transaction tx2=session2.beginTransaction();
session2.update(customer);// 通过调用 update() 方法将游离状态的 customer 对象,再次转化成持久化状态
session2.delete(customer);// 调用 delete() 方法后,当清空缓存时,会将 customer 对象移出缓存,同时会在数据库中生成 delete 事务,来删除 customer 对象对应的数据记录
tx.commit();
session.close();
那么这个方法到底执行了哪些步骤呢?它会按照下面的步骤进行操作:
一、            首先会在缓存中寻找需要更新的实体对象,如果找到就立刻返回,从这里我们可以看出如果对一个已经处于 persistent 的实体对象执行 update() 方法,将不会产生任何作用。
二、            然后当提交事务进行缓存清理时,将会通过脏数据检查,确定变化的属性,然后生成 update SQL 语句完成数据的更新。
这里有一个问题我们要强调一下,那就是只要通过 update() 方法将一个游离对象与 session 相关联,那么不论这个游离的实体对象的属性是否发生改变,都会执行 update SQL 语句。如下面的代码:
 
Transaction tx=session.beginTransaction();
session.update(customer);
tx.commit();
session.close();
在这段代码中并没有修改 customer 对象的任何属性值,但是也会执行一个 update SQL 语句,如果你希望在没有改变实体对象属性值的情况下不去执行 update SQL 语句,那么你要开启实体对象 <class> 元素的 ”select-before-update” 属性,将其设置为 ”true”, 这个属性默认为 ”false” 。如下进行配置:
<class name=”com.neusoft.entity.Customer” table=”customer” select-before-update=”true”>
如果启用了这个属性配置,那么在清理 session 缓存之前,会首先执行类似如下的一条 SQL 语句:
Select * from customer where id=’1’;
查询处所有的 customer 实体在数据库中对应的属性值,然后逐条与缓存中属性值进行比较,如果发生了改变,那么将会生成 update 操作进行数据更新,如果没有发生改变那么将不会进行 update 操作。要跟据实际需求情况来决定是否开启这个选项,如果实体对象的属性不会经常发生改变,那么就应该开启这个选项,以免执行多余的 update 操作。如果实体对象的属性会经常发生改变,那么就没必要开启这个选项,以免在执行 update 操作前再执行多余的 select 语句。
 
注:( 1 )、当执行对一个游离实体对象执行 session.update() 操作时,如果在数据库中不存在这个实体对应的纪录,那么这个操作将会抛出异常。
    2 )、当执行 session.update() 方法将一个游离对象与 session 关联时,如果此时在缓存中已经存在了与该实体对象具有相同 OID 的持久化对象,那么这个方法会抛出异常。如下面代码:
Customer customer1=new Customer(“1”,“zx”,27,images);
Session session1=sf.openSession();
Transaction tx=session1.beginTransaction();
session.save(customer1);
session.flush();
tx.commit();
session1.close();
 
Session session2=sf.openSession();
Transaction tx2=session2.beginTransaction();
Customer othercustomer=(Customer)session2.load(Customer.class,”1”);
session2.update(customer1)
tx2.commit();
session2.close();
当再次将游离对象 customer1 session2 关联时,此时因为 load() 操作,在缓存已经加载了一个和 customer1 具有相同 OID othercustomer 对象,此时由于 Hibernate 缓存的对象缓存机制不允许把 OID 相同的对象缓存,所以会抛出异常。
2、       Session.saveOrUpdate():
这个方法包含了 save() 方法和 update() 方法的特点,如果传入该方法的是一个游离对象,那么这个方法就会执行 update 操作,如果传入该方法的是一个临时对象,那么这个方法就会执行 insert 操作。这个方法幕后的工作原理如下:
a)         首先在缓存寻找,如果找到待保存的操作就直接返回。
b)         如果实体实现了拦截方法,那么就执行 isUnsaved() 方法,判断实体对象状态。
c)         如果实体处于临时状态就执行 save(), 如果实体处于游离状态那么就执行 update()
这里存在一个问题,那就是 Hibernate 是怎样判断一个实体是处于游离态还是临时状态的?如果实体满足下面的一个条件,就认为这个实体处于临时状态。
.Java 对象的 OID 值为 null
. 如果 Java 对象具有 version 属性(将在并发加锁部分讲解)且为 null
. 如果实体的 <id> 设置了属性 unsaved-value ,而且 OID 值与 unsaved-value 值相等。
. 如果实体的 version 属性设置了 unsaved-value ,并且 version 属性的值与 unsaved-value 值相等。
. 如果实体实现了 Interceptor, 而且 Interceptor.isUnsaved() 方法返回 true
满足这些条件中的一个,这个实体就被认为是临时对象。
3、       Session.delete():
delete() 方法用于从数据库中删除一个或一批实体所对应的数据,如果传入的对象是持久化对象,么当清理缓存时,就会执行 delete 操作。如果传入的是游离对象,那么首先会使该对象与 session 相关联,然后当清理缓存时,再执行 delete 操作。看如下代码:
Session session=sessionFactory().openSession();
Transaction tx=session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,”1”);
session.delete(customer);// 计划执行一条 delete 语句
tx.commit();// 清理缓存,执行一条 delete 语句
session.close();// 关闭 session, 这时将会把 customer 对象从缓存中删除。
如果上面的代码中的 customer 对象是一个游离对象,那么当执行 session.delete() 方法时,会首先将游离的 customer 对象与 session 相关联,然后再清理缓存时,再执行 delete 操作。如果你想一次删除多条数据,那么可以采用一个重载的 delete() 方法: delete(“from Customer c where c.id>’8’ ”); 这个方法可以删除符合条件的所有数据。

猜你喜欢

转载自larry1001.iteye.com/blog/1754082