背景:

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

  1. SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
  2. Session s = sf.openSession();
  3. Transaction tran = s.beginTransaction();
  4. Animal animal1 = new Animal();
  5. animal1 .setName(“tom”);
  6. s.save(animal1 );
  7. animal1 .setName(“mary”);
  8. s.update(animal1 );
  9. Animal animal2 = new Animal ();
  10. animal2.setName(“tom”);
  11. s.save(animal2);
  12. 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就可以,

  1. SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
  2. Session s = sf.openSession();
  3. Transaction tran = s.beginTransaction();
  4. Animal animal1 = new Animal();
  5. animal1 .setName(“tom”);
  6. s.save(animal1 );
  7. animal1 .setName(“mary”);
  8. s.update(animal1 );
  9. s.flush();
  10. Animal animal2 = new Animal ();
  11. animal2.setName(“tom”);
  12. s.save(animal2);
  13. s.flush();
  14. tran.commit();

这样就能按照我们的想法顺序缓存sql语句了有木有?

4、总结:

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

【Hibernate框架】flush机制的更多相关文章

  1. 从一次异常中浅谈Hibernate的flush机制

    摘自http://www.niwozhi.net/demo_c70_i1482.html http://blog.itpub.net/1586/viewspace-829613/ 这是在一次事务提交时 ...

  2. java框架篇---hibernate之缓存机制

    一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...

  3. 深入浅出学习hibernate框架(三):java的反射机制

    上篇博客写到了JDBC的基本操作,今天准备写一篇关于JAVA反射机制的文章,因为java的反射机制和上一篇JDBC都是Hibernate框架的基本要素.在Hibernate的运行机制中,这两块的内容正 ...

  4. Hibernate框架—简介

    ORM对象/关系数据库映射 ORM全称Object/Relation Mapping,对象/关系数据库映射,可以理解成一种规范.该框架的基本特征:完成面向对象的编程语言到关系数据库之间的映射. ORM ...

  5. Hibernate框架的总结

    hibernate 简介:hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用面向对象的思想来操纵数据库.hibernate核心接口 ...

  6. J2EE进阶(八)Hibernate与延迟加载机制探究

    Hibernate与延迟加载机制探究 前言 Hibernate对象关系映射提供延迟的与非延迟的对象初始化.非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来.这有时会导致成百的 ...

  7. hibernate框架学习之核心API

    ConfigurationSessionFactorySessionTransactionQueryCriteria Configuration Configuration对象用于封装Hibernat ...

  8. Hibernate框架第二天

    ### Hibernate的持久化类 ### ---------- **什么是持久化类** 1. 持久化类:就是一个Java类(咱们编写的JavaBean),这个Java类与表建立了映射关系就可以成为 ...

  9. Hibernate框架学习笔记

      Hibernate 是一个 JDO( Java Data Objects)工具.它的工作原理是通过文件把值对象(Java对象)和 数据库表之间建立起一个映射关系,还提供数据查询和获取数据的方法. ...

  10. Hibernate框架基本使用

    时间:2017-1-16 00:36 --什么是Hibernate    Hibernate是一个开放源代码的关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以使用对象编程思 ...

随机推荐

  1. Java 静态内部类与非静态内部类 学习记录.

    目的 为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合 ...

  2. angularjs 新窗口打开

    原文链接:angularjs 中state.go 跳转并且打开新的浏览器窗口 业务需要,需要点击打开一个新窗口,并且是点击事件触发的打开新窗口: $scope.lookLook =function(d ...

  3. Red5 1.0.0RC1 集成到tomcat6.0.35中运行&部署新的red5项目到tomcat中

    1.下载red5-war-1.0-RC1.zip 解压之得到 ROOT.war 文件. 2.处理tomcat. 下载apache-tomcat-6.0.35-windows-x86.zip包,解压到你 ...

  4. MATLAB-RSP 随笔

    1.Getting Started with Signal Analyzer App 161216 (1) 在命令行中输入:signalAnalyzer. (2)在工作空间中选择要分析的信号

  5. 【学习笔记】Struts2之配置处理结果

        Action只是Struts2控制器的一部分,所以它不能直接生成对浏览者的响应.Action只负责生成响应的视图组件,通常是JSP页面,而Action会为JSP页面提供显示数据.     Ac ...

  6. 信息安全比赛总结(21ic转帖)

    我们的题目是基于这个ZedBoard的__视频流的人脸识别识别的算法采用的是PCA,,但是在后期的调试和实验中发现,,PCA的效果很容易受到环境,比如光照强度,背景,摄像头像素等影响:如果后期的改进的 ...

  7. Quick Cocos 旋转子弹的实现中我学到的

    self 在lua中相当于java中的this lua中的任何变量在没有赋值前, 都可以看做是nil  lua变量有3种,成员变量: self.变量名 = 局部变量: local 变量名 = 全局变量 ...

  8. Java 中正确获取中文字符串长度

    /** * 获取字符串的长度,如果有中文,则每个中文字符计为2位 * * @param value * 指定的字符串 * * @return 字符串的长度 */ public static int l ...

  9. RabbitMQ 集群安装过程详解

    一.安装Erlang 1.rabbitMQ是基于erlang的,所以首先必须配置erlang环境. 从erlang官网下载 otp 18.3.下载链接:http://erlang.org/downlo ...

  10. nubia Z5 mini 小牛 黑砖qhsusb dload修复

    给手机分区,用了分区助手,将一些分区移动. 结果分区坏了,只有两三个分区在电脑显示,当时晕菜把数据线拔了重插. 手机变砖,不能启动,黑屏,不能进recovery... 参考 http://bbs.nu ...