session flush测试:
session flush方法主要做了两件事:
1 清理缓存
2 执行sql(不是提交事务)
session在什么情况下执行flush
1 默认在事务提交时
2 显式的调用flush
3 在执行查询前,如:iterate
hibernate按照save(insert),update,delete顺序提交相关的操作
hibernate执行的顺序如下,
(1)生成一个事务的对象,并标记当前的Session处于事务状态(注:此时并未启动数据库级事务)。
(2)应用使用s.save保存对象,这个时候Session将这个对象放入entityEntries,用来标记对象已经和当前的会
话建立了关联,由于应用对对象做了保存的操作,Session还要在insertions中登记应用的这个插入行为(行为包括:对象引用、对象 id、Session、持久化处理类)。
(3)s.evict将对象从s会话中拆离,这时s会从entityEntries中将这个对象移出。
(4)事务提交,需要将所有缓存flush入数据库,Session启动一个事务,并按照insert,update,……,delete的顺序
提交所有之前登记的操作(注意:所有insert执行完毕后才会执行update,这里的特殊处理也可能会将你的程序搞
得一团糟,如需要控制操作的执行顺序,要善于使用flush),现在对象不在entityEntries中,但在执行insert的行
为时只需要访问insertions就足够了,所以此时不会有任何的异常。异常出现在插入后通知Session该对象已经插入
完毕这个步骤上,这个步骤中需要将entityEntries中对象的existsInDatabase标志置为true,由于对象并不存在于 entityEntries中,此时Hibernate就认为insertions和entityEntries可能因为线程安全的问题产生了不同步(也 不知道Hibernate的开发者是否考虑到例子中的处理方式,如果没有的话,这也许算是一个bug吧),于是一个 net.sf.hibernate.AssertionFailure就被抛出,程序终止
session.evict(obj),会把指定的缓冲对象进行清除
session.clear(),把缓冲区内的全部对象清除,但不包括操作中的对象
------------------------------------------------------------------------
<id name="id">
<generator class="uuid"/>
</id>
因为id的主键生成策略采用的是uuid,所以调用完save后,只是将user对象纳入到session的管理
不会发出insert语句,但是id已经生成,session中existsInDatebase状态为false
session.save(user);
调用flush,hibernate会清理缓存,执行sql
如果数据库的隔离级别为提交读,那么我们可以看到flush过的数据
并且session中existsInDatebase状态变为true
session.flush();
默认情况下commit操作会先执行者flush清理缓存,所以不用显式的调用flush
commit后数据无法回滚
session.getTransaction().commit();
<id name="id">
<generator class="native"/>
</id>
如果id的主键生成策略采用的是native,调用save(user)时会发出insert语句,返回由数据库生成的id,
user对象纳入到session的管理,session中existsInDatebase状态为true
-----------------------------------------------------------------
<id name="id">
<generator class="uuid"/>
</id>
session.save(user);
将user对象从session中逐出,即session的EntiryEntries属性中逐出
session.evict(user);//清理缓存
无法成功提交,因为hibernate在清理缓存时,在session的insertions集合中取出user对象进行insert操作后
需要更新entityEntries属性中的existsnDatabase为true,而我们采用evict已经将user从session中
逐出了,所以找不到相关数据,无法更新,抛出异常
session.getTransaction().commit();
----------------------------------------------------------------
<id name="id">
<generator class="uuid"/>
</id>
session.save(user);
flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user
清除,并且设置session中existsInDatabase的状态为true
session.flush(user);
将user对象从session中逐出,即session的EntityEntries属性中逐出
session.evict(user);//清理缓存
可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到user对象
所以就不会发出insert语句,也不会更新session中的existsInDatabase的状态
session.getTransaction().commit();
-----------------------------------------------------------------
<id name="id">
<generator class="native"/>
</id>
session.save(user);
将user对象从session中逐出,即session的EntityEntries属性中逐出
session.evict(user);//清理缓存
可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到user对象
所以就不会发出insert语句,也不会更新session中的existsInDatabase的状态
session.getTransaction().commit();
-----------------------------------------------------------------
<id name="id">
<generator class="assigned"/>
</id>
session.save(user);
user.setName("张三");
session.update(user);
User user2=new User();
user2.setId("003");
user2.setName("李四");
session.getTransaction().commit();
结果:
insert into ...
insert into ...
update t_user ...
hibernate按照save(insert),update,delete顺序提交相关的操作
-----------------------------------------------------------------
<id name="id">
<generator class="assigned"/>
</id>
session.save(user);
user.setName("张三");
session.update(user);
因为我们在session.update(user)后执行了flush,所以在以commit清理缓存时执行flush前的sql就不会发出.
session.flush();//在这里flush操作就可以了
User user2=new User();
user2.setId("003");
user2.setName("李四");
session.getTransaction().commit();
结果:
insert into ...
update t_user ...
insert into ...
按照我们想要顺序save(insert),update,save(insert)的顺序提交操作
-----------------------------------------------------------------