背景:

一个偶然的机会,我做了一个例子,中间我遇到了一个有意思的问题,就是在执行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. AutoComplete

    aspx页面 需要引用的文件: <link rel="stylesheet" type="text/css" href="css/jquery. ...

  2. Bubble Cup 8 finals A. Fibonotci (575A)

    题意: 定义类循环序列为 长度无限,且除了有限个元素外,均满足s[i] ≡ s[i mod N] (i≥N). 现在有数列F,定义为 F[i] = s[i-2]*F[i-1] + s[i-1]*F[i ...

  3. jQuery中Animate进阶用法(一)

    jQuery中animate的用法你了解多少呢?如果仅仅是简单的移动位置,显示隐藏,哦!天哪你在浪费资源!因为animate太强大了,你可以有很多意想不到的用法!让我们一起研究一下吧~~ 首先要了解j ...

  4. 一张图告诉你,只会HTML还不够!

    会了HTML和HTML5语法,你就真的会了HTML吗,来看这张图!是这本<超实用的HTML代码段>入门实例书的导览!熊孩子们,赶紧学习去吧! 如果一半以上的你都不会,必须看这本书,阿里一线 ...

  5. 2012Chhengdu K - Yet Another Multiple Problem

    K - Yet Another Multiple Problem Time Limit:20000MS     Memory Limit:65536KB     64bit IO Format:%I6 ...

  6. HTTP缓存

    本文是<HTTP权威指南>读书笔记 Web缓存是可以自动保存常见文档副本的设备.当Web请求抵达缓存时,如果本地在“已缓存”的的副本,就可以从本地存储设备而不是原始服务器中提取这个文档.使 ...

  7. pycharm 2016.3 注册码

    Choose Active Code 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYX ...

  8. java后台对前端输入的特殊字符进行转义

    转自:http://www.cnblogs.com/yangzhilong/p/5667165.html java后台对前端输入的特殊字符进行转义 HTML: 常见的帮助类有2个:一个是spring的 ...

  9. Mysql Sql语句令某字段值等于原值加上一个字符串

    MySQL连贯字符串不能利用加号(+),而利用concat. 比方在aa表的name字段前加字符'x',利用: update aa set name=concat('x',name); 替换: UPD ...

  10. Spring MVC返回Map格式JSON数据

    问题描述: ajax中走error : function(e) {} 问题背景: 在测试controller层时,试过了ResponseEntity<ResponseModel>这种类型返 ...