关闭

【Hibernate框架】flush机制

1580人阅读 评论(16) 收藏 举报
分类:


背景:

       一个偶然的机会,我做了一个例子,中间我遇到了一个有意思的问题,就是在执行commit方法之前,做了两次save操作,如下:

SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
Session s = sf.openSession();
Transaction tran = s.beginTransaction();
Animal animal1 = new Animal();
animal1 .setName(“tom”);
s.save(animal1 );

animal1 .setName(“mary”);
s.update(animal1 );

Animal animal2 = new Animal ();
animal2.setName(“tom”);
s.save(animal2);
tran.commit();
这样执行之后,报了一个:关于session主键冲突的异常,这之前,我也见过一个,就是整棵继承树映射一张表的时候,主键自增长不配置时,这个,我没有弄啊!然后开始这种查找资料,后来知道,commit方法会隐形的调用一个flush方法,而这个方法不是按照我们代码来提交事务的,而是会按着save、update、delete这个顺序来提交事务,所以会连续有两个save变成持久化对象,而造成session生成的Oid重复。


也就是因为这个,我对flush感了兴趣,下面我们介绍一下关于flush的那些事:

1、flush有什么用?

       调用flush方法,会按save,update,delete顺序执行,把缓存中的数据flush入数据库中,并清空缓存区;这里注意啊,这里只是将缓存中的数据同步到数据库中,这里并没有在数据库中insert数据,可以理解为把缓存内数据同步到一张临时表内(缓存区),这时候,直接查询数据库是没有新添数据的,但是使用发送sql语句查询却可以查出数据来(前提:数据库隔离级别要为 未提交读),当提交事务时,数据库事务管理器提交事务执行提交过来的sql语句,修改数据库数据。也就是说,只有commit才会更改数据库数据。

整理一下啊:flush方法的主要作用就是清理缓存,强制数据库与Hibernate缓存同步,以保证数据的一致性。其实在session持久化操作和数据库中之间还有一层对象缓冲区

flush的主要动作就是向数据库发送一系列的sql语句,并执行这些sql语句,但是不会向数据库提交。而commit方法则会首先调用flush方法,然后提交事务。这就是为什么我们仅仅调用flush的时候记录并未插入到数据库中的原因,因为只有提交了事务,对数据库所做的更新才会被保存下来。因为commit方法隐式的调用了flush,所以一般我们都不会显示的调用flush方法。


2、关于主键生成策略的一点隐私:

       当你的id主键生成策略为native,调用session.save后,将执行insert语句,返回有数据库生成的id 纳入了session的管理,修改了session中existsInDatabase状态为true,如果数据库的隔离级别设置为未提交读,那么我们可以看到save过的数据 ;

       当id主键生成策略采用的是uuid,调用完成save后,只是将user纳入到了session的管理,不会发出insert语句,但是id已经生成,session中existsInDatabase状态为false;


3、最后那如何解决上面的问题呢,很简单,在update之后,执行session.flush,然后再第二个save之后,再执行一次flush就可以,

SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
Session s = sf.openSession();
Transaction tran = s.beginTransaction();
Animal animal1 = new Animal();
animal1 .setName(“tom”);
s.save(animal1 );

animal1 .setName(“mary”);
s.update(animal1 );
s.flush();
Animal animal2 = new Animal ();
animal2.setName(“tom”);
s.save(animal2);
s.flush();
tran.commit();
这样就能按照我们的想法顺序缓存sql语句了有木有?

4、总结:

       由于flush()的特殊处理机制,虽然不建议使用此方法,但是在一些复杂的事务处理过程中,加入此方法虽然会破坏事务的一个提交的完整性,但是可以规避一些不可预见的异常情况!

2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:176344次
    • 积分:7711
    • 等级:
    • 排名:第2717名
    • 原创:143篇
    • 转载:5篇
    • 译文:0篇
    • 评论:2935条
    联系方式
    点击这里给我发消息
    博客专栏