背景:

一个偶然的机会,我做了一个例子,中间我遇到了一个有意思的问题,就是在执行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. 记录我学github的路程(三)

    2015-12-22 更新 一.Bug分支 1,假设如下场景,你正在dev分支工作,突然接到一个修复代号为101的bug的任务时,dev的东西还没不能提交,但是bug需要马上修复. Git提供了一个s ...

  2. [转]PhpStorm 超强语言模板的支持

    最近遇到一些PhpStorm编程的问题: 在使用Zen Coding插件时,PHPStorm不像Notepad++那样随便使用.PHPStorm只有在编辑识别为HTML的文件时才可以使用Zend Co ...

  3. REDHAT一总复习1 ssh配置 禁用root用户SSH连接

    生成SSH公钥 $ ssh-keygen 生成的公钥安装到指定的服务器上,这里安装到desktop0上的student账户 $ ssh-copy-id desktop0 $ su - 禁用root用户 ...

  4. Gedit 解决中文显示乱码问题

    详细请参考:http://wiki.ubuntu.org.cn/Gedit%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81 具体原因是Gedit的默认编码设置没有添加中文编码所 ...

  5. linux系统内核流转浅析

    SJTUBEAR  原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 我们通过简单 ...

  6. jquery on()

    为多个元素绑定同一个事件: $(document).on('click', '#header .fixed-feedback-bn, #sb-sec .feedback-bn', function ( ...

  7. IIS部署遇到的一些问题

    IIS部署时候会遇到一些具体的问题,记录一下.此处的部署环境为Windows Server 2012 64位版本 1.基本部署:角色和功能管理-->web服务器,勾选相应的服务与功能,然后安装即 ...

  8. mac 关闭&&显示隐藏文件命令

    打开终端,输入: defaults write com.apple.finder AppleShowAllFiles -bool true 此命令显示隐藏文件 defaults write com.a ...

  9. overridePendingTransition简介

    1 Activity的切换动画指的是从一个activity跳转到另外一个activity时的动画. 它包括两个部分:一部分是第一个activity退出时的动画:另外一部分时第二个activity进入时 ...

  10. linux Mint wine安装qq,桌面快捷键配置

    在桌面新建qq.desktop文件,添加以下内容 #!/usr/bin/env xdg-open[Desktop Entry]Comment=QQTerminal=falseName=QQExec=w ...