攻城狮在路上(壹) Hibernate(六)--- 通过Hibernate操纵对象(上)

一、Hibernate缓存简介
  Session接口是Hibernate向应用程序提供的操纵数据接口的最主要接口,它提供了基本的保存、更新、删除和加载Java对象的方法。
  Session具有一个缓存,位于缓存中的对象称为持久化对象,Session能够在某些时间点来同步更新数据库,这一过程即为清理缓存。
  Hibernate把对象分为4种状态:持久化状态、临时状态、游离状态和删除状态。

二、Session的缓存
  Session的缓存由一系列Java集合构成的。
  1、Session缓存的作用
    A、减少访问数据库的频率。
    B、当缓存中的持久化对象之间存在循环关联关系时,Session保证不会出现访问对象图的死循环,以及由死循环引起的JVM堆栈溢出异常。
    C、保证数据库中的相关记录和缓存中的相应对象保存同步。Session通过在清理缓存时进行脏检查来同步。
  2、脏检查及清理缓存的机制
  当一个对象被加入到Session缓存中时,Session会为该对象的值类型的属性复制一份快照。在清理缓存进行脏检查时,就是拿对象的当前属性和它的快照进行对比,据此判断是否发生了变化。
  另外,当对象属性发生变化时,Session并不会立即清理缓存和执行相关的SQL操作,而是在特定的时间才清理缓存。这样的好处就是Session能够把几条相关的SQL语句合并为一条SQL,从而减少访问数据库的次数。

  Session清理缓存时,按照以下顺序执行SQL语句(了解)

?





1

2

3

4

5

6

A、按照session.save()方法先后顺序,执行所有对实体进行插入的insert语句。

B、执行所有对实体进行更新的update语句。

C、执行所有对集合进行删除的delete语句。

D、执行所有对集合元素进行删除、更新或者插入的SQL语句。

E、执行所有对集合进行插入的insert语句。

F、按照应用程序调用session.delete()方法的先后顺序,执行所有对实体进行删除的delete语句。

  Session会在以下时间点清理缓存

?





1

2

3

A、当应用程序调用org.hibernate.Transaction分commit()方法时,先清理缓存,再提交事务。

B、当应用程序执行一些查询操作时,如果缓存中的持久化对象属性发生了变化,就会先清理缓存。

C、当应用程序显式调用Session的flush()方法的时候。

  例外情况:如果对象使用native生成器来生成OID,name当调用Session的 save()方法保存对象时,会立即执行insert语句。

  也可以通过Session.setFlushMode()方法来显式的设定清理缓存的时间点。

  多数情况下应用程序不需要显式的调用flush()方法,以下常见除外:
    A、插入、删除或更新某个持久化对象会引发数据库中触发器的时候。
    B、在应用程序中混合使用Hibernate
API和JDBC API的时候。
    C、JDBC驱动程序不健壮,导致Hibernate在自动清理缓存模式下无法正常工作的时候。

三、Java对象在Hibernate持久化层的状态
  1、状态描述
    A、临时状态(transient):刚用new语句创建,还没有被持久化,并且不处于Session的缓存中。
    B、持久化对象(persistent):已经被持久化,并且加入到Session缓存中。
    C、删除状态(delete):不再处于Session的缓存中,并且Session已经计划将其从数据库中删除。
    D、游离状态(detached):已经被持久化,但是不再处于Session的缓存中。
  2、状态转换图

  
  3、临时对象的特征
    A、在使用代理主键的情况下,OID通常为NULL。
    B、不处于Session的缓存中,不被任何一个Session实例关联。
    C、在数据库中没有对应的记录。

四、持久化对象的特征
  1、OID不为null。
  2、位于一个Session实例的缓存中。持久化对象总是被一个Session实例关联。
  3、持久化对象和数据库中的相关记录对应。
  4、Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库。

五、被删除对象的特征
  1、OID不为null。
  2、从一个Session实例的缓存中删除。
  3、被删除对象和数据库中的相关记录对应。
  4、Session已经计划将其从数据库中删除。
  5、Session在清理缓存时,会执行SQL
delete语句,删除数据库中的相应记录。
  6、一般情况下,应用程序不应该再使用被删除的对象。

六、游离对象的特征
  1、OID不为null。
  2、不再位于Session的缓存中。
  3、游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它相对应的记录。

  游离对象和临时对象的相同之处:两者都不被Session关联,因此不会保证它们的属性变化与数据库保存同步。
  游离对象和临时对象的不同之处:游离对象是由持久化对象转变过来的,因此数据库中可能存在对应的记录,而临时对象在数据库中没有与之对应的记录。
  游离对象与被删除对象的相同之处:两者都不位于Session的缓存中,并且数据库中都可能存在对应的记录。
  游离对象与被删除对象的不同之处:游离对象与Session完全脱离关系,而对于被删除对象,Session会计划将其从数据库中删除,在清理缓存时会执行删除操作。

七、Session接口的详细用法
  1、Session的save()和persist()方法
    save()方法使一个临时对象转变为持久化对象。注意应该禁止应用程序修改OID。
    persist()方法和save()方法类似,区别在于该方法是在Hibernate3版本中财出现的。且如果在事务边界以外调用persist()方法时,不会执行SQL
insert语句。
  2、Session的load()和get()方法:
    这两个方法都能根据给定的OID从数据库中加载一个持久化对象。
    区别在于:
      A、当数据库中不存在与OID对应的记录时,load()方法抛出OjbectNotFoundException,而get()方法返回null。
      B、两者采用不同的检索策略(检索策略后续描述)。load()方法根据<class>元素的lazy属性决定是否进行懒加载,而get()方法会忽略lazy属性,采用立即检索策略。
    使用场景:
      A、如果加载一个对象的目的是访问它的各个属性,可以用get()方法。
      B、如果加载一个对象时为了删除它,或者威力建立和别的对象的关联,可以用load()方法。
  3、Session的update()方法
    update()方法使一个游离对象转变为持久化对象,并计划执行一条update语句。
    如果希望Session仅在修改了对象的属性时才执行update语句,可以把<class>元素的select-before-update设置为true。
    当update()方法关联一个游离对象时,如果在Session缓存中已经存在相同OID的持久化对象,会抛出异常。
  4、Session的saveOrUpdate()方法
    saveOrUpdate()方法同时包含了save()和update()方法。如果传入的参数是临时对象,调用save()方法;如果传入的参数是游离对象,就调用update()方法;如果传入的是持久化对象,就直接返回。
  满足下列任何一个条件,Hibernate就会认为该对象时临时对象:
    A、Java对象的OID为null。
    B、Java对象具有version版本控制属性并且取值为null(不明白)。
    C、在映射文件中为<id>元素设置了unsaved-value属性,并且Java对象的OID与这个属性值匹配。
    D、在配置文件中为version版本控制属性设置了unsaved-value属性,并且Java对象的version版本控制属性的取值与该属性值匹配。
    E、为Hibernate的Interceptor提供了自定义的实现,并且Interceptor实现类的isUnsaved()方法返回Boolean.TRUE。
  5、Session的merger()方法
    merge()方法能够把一个游离对象的属性复制到一个持久化对象中。
  6、Session的delete()方法
    delete()方法用于从数据库中删除一个Java对象。既可以删除持久化对象,也可以删除游离对象。
  7、Session的replicate()对象
    该方法能够把一个数据库中的对象复制到另一个数据库中。(暂不关注)

八、级联操作对象图
  1、cascade属性表

声明:该文所有内容均来自《精通Hibernate:Java对象持久化技术详解》[孙卫琴
电子工业出版社] 一书。该文的目的仅仅作为学习笔记。若需要转载,请注明原书相关信息。

时间: 2024-10-09 17:25:24

攻城狮在路上(壹) Hibernate(六)--- 通过Hibernate操纵对象(上)的相关文章

攻城狮在路上(壹) Hibernate(七)--- 通过Hibernate操纵对象(下)

一.与触发器协同工作: 当Hibernate与数据库的触发器协同工作时,会出现以下两类问题: 1.触发器使Session缓存中的数据和数据库中的不一致: 出现此问题的原因是触发器运行在数据库内,它执行的操作对Session是透明的. 解决方案:在执行完包含有触发器的操作之后,立刻调用Session的flush()和refresh()方法,迫使Session的缓存与数据库同步. 2.Session的update()方法盲目的激发触发器: 这种情况主要发生在Session调用update()或sav

攻城狮在路上(壹) Hibernate(十)--- 映射值类型集合

一.映射Set(集):未排序,无重复. 实例代码: ? 1 2 3 4 <set name="images" table="IMAGES" lazy="true" > <key column="CUSTOMER_ID" /> <element column="FILENAME" type="string" not-null="true"/

攻城狮在路上(壹) Hibernate(十八)--- 管理Hibernate的缓存

一般Session的缓存被称为Hibernate的第一级缓存,SessionFactory的外置缓存是一个可配置的缓存插件,称为Hibernate的第二级缓存.一.缓存的基本原理: 1.持久化层的缓存的范围: A.事务范围:缓存只被当前事务访问. B.进程范围:缓存被进程内的所有事务共享.需要采取必要的隔离机制.缓存介质可以使内存或硬盘. C.集群范围:缓存被同一个机器或多个机器上的多个进程共享.缓存中的数据被复制到集群环境中的每一个进程节点,进程之间通过远程通信来保证缓存中的数据一致性,缓存中

攻城狮在路上(壹) Hibernate(十七)--- Hibernate并发处理问题

一.多个事务并发运行时的并发问题: 总结为第一类丢失更新.脏读.虚读.不可重复读.第二类丢失更新. 1.第一类丢失更新: 撤销一个事务时,把其他事务已提交的更新数据覆盖. 2.脏读: 一个事务读到另一个事务未提交的更新数据. 3.虚读(幻读): 一个事务读到另一个事务已提交的新插入的数据. 4.不可重复读: 一个事务读到另一个事务已提交的更新数据. 5.第二类丢失更新: 这是不可重复读的特例,一个事务覆盖另一个事务已提交的更新数据.二.数据库系统的锁的基本原理: 数据库系统采用锁来实现事务的隔离

攻城狮在路上(壹) Hibernate(九)--- Hibernate的映射类型

Hibernate采用映射类型作为Java类型和SQL类型的桥梁,对应type属性.分为两种:内置映射类型和客户化映射类型.一.内置映射类型: 1.Java基本类型的Hibernate映射类型: Java基础类型的Hibernate映射类型 Hibernate映射类型 Java类型 标准SQL类型 大小和取值范围 integer或者int int或者java.lang.Integer INTEGER   long long BIGINT   short short SMALLINT   byte

攻城狮在路上(叁)Linux(二十六)--- linux文件系统的特殊查看与操作

一.boot sector 与 super block的关系: 1.boot sector用于存放引导装载程序,占用1024个字节. 2.super block的大小也为1024字节. 3.若block大小为1k,则boot sector和super block各占一个block. 4.若block大于1K(2K/4K)时,则两者都位于第一个block中. 二.磁盘空间的浪费问题:暂不考虑. 三.利用GUN的parted命令进行分区行为: 因为fdisk不支持高于2TB的分区. 命令格式: pa

攻城狮在路上(叁)Linux(十六)--- 命令与文件的查找

一.脚本文件的查询: 1.命令格式:which [-a] command; <==通过PATH来查找. -a:列出所有的,而不是仅列出第一个. 示例: which ifconfig; 注意:由于不同的用户PATH不同,所以结果或许也有区别. 二.文件名的查找: 1.whereis [-bmsu] 文件或目录名  <==通过数据库来查找,所以不同的用户查到的结果是一致的. 参数说明: -b:只找二进制格式的文件. -m:只找在说明文件manual路径下的文件. -s:只找source源文件. -

攻城狮在路上(叁)Linux(二十二)--- linux磁盘挂载与卸载 mount umount

挂载就是将文件系统与目录结合的操作.挂载点就是目录,该目录就是进入分区或文件系统的入口. 一.挂载前的注意事项: 1.单一文件系统不应该被重复挂载在不同的挂载点中. 2.单一目录不应该重复挂载多个文件系统. 3.即将作为挂载点的目录理论上应该都是空目录才对. 注意:对应2和3,如果要挂载的目录不为空,那么挂载了新的文件系统之后,原来的目录会暂时消失(并非覆盖掉),系统会显示最新挂载的文件系统.新分区被卸载之后,原来的文件系统会重新显示出来. 二.命令介绍 mount [-t 文件系统] [-L

攻城狮在路上(叁)Linux(二十八)--- 打包命令:tar

首先介绍一下tar打包命令的基本格式,下面的三种之间不能混淆. tar [-j|-z] [cv] [-f 新文件名] file1 file2 ...; tar [-j|-z] [tv] [-f 新文件名]; <== 查看文件名 tar [-j|-z] [xv] [-f 新文件名] [-C 目录]; <== 解包 参数说明: -c:新建打包文件,搭配-v来查看过程中被打包的文件名 -t:查看打包文件的内容包含哪些文件名 -x:解包或解压缩功能.可搭配大写C来指定解压目录 ------------

攻城狮在路上(叁)Linux(三十)--- 光盘写入工具

一.基本步骤: 1.用mkisofs命令将所需备份的数据构建成镜像文件. 2.用cdrecord命令将镜像文件刻录至光盘或者DVD中. 二.mkisofs:新建镜像文件 mkisofs [-0 镜像文件] [-rv] [-m file] 待备份文件... [-V vol] graft -point isodir=Systemdir... 参数说明: -o:后面指定镜像文件 -r:通过RockRidge产生支持UNIX/Linux的文件数据,可以记录较多信息. -v:显示构建过程 -m file: