Hibernate学习二---持久化对象的三种状态和缓存

1、持久化对象的3个状态。

  瞬时、持久、托管为hibernate持久化对象的三个状态。

  最大的区别在于是否受到session管理,受session管理的为持久态。

  不受session管理但在数据库中有主键ID的为托管态。

  不受session管理并且在数据库中没有主键ID(OID)的为瞬时态。

   

 

是否有持久化标识

session是否存在

数据库中是否有

瞬时态对象-临时状态

n

n

n

持久态对象

y

y

y/(n:没有提交)

脱管态对象

y

n

y

 

  

  对于三者:在session中存在的,就是持久化对象,不存在的就是瞬时或脱管对象。

  对于瞬时和脱管对象:有oid(持久化标识)的就脱管对象,没有的就是瞬时对象。

   

  三种状态的相互转换:

  瞬时态:

      如何直接获取:---new出来

      转换到持久态:--save、saveorupdate保存操作

      转换到托管态:--setId设置OID持久化标识(这个ID必须是数据库中存在的,否则仅是一个属性)

  持久对象:

      如何直接获得 ---- 通过session查询方法获得 get、load、createQuery、createCriteria

           转换到瞬时态 ---- delete 删除操作 (数据表不存在对应记录 )(其实还有id,只是不叫OID)

             转换到脱管态 ---- close 关闭Session, evict、clear 从Session清除对象

  托管对象: 

        如何直接获得 ----- 无法直接获得 ,必须通过瞬时对象、持久对象转换获得

             转换到瞬时态 ---- 将id设置为 null,或者手动将数据库的对应的数据删掉

                  转换到持久态 ---- update、saveOrUpdate、lock (对象重新放入Session ,重新与session关联)

 

2、Hibernate的一级缓存

    当需要所有字段都更新,需要将所有属性都赋值。否泽为null,托管态对象设置id,然后其他属性赋值,update时,不会提交sql语句,只有当commit时才提交。因为id没有更改,更新一级缓存的快照时,可以单个属性更新。不需要所有字段都赋值,持久态对象进行操作,先查询。

    Customer customer= (Customer) session.get(Customer.class,2);
    customer.set
    commit
    多表关联时,只有持久关联持久,不能持久关联瞬时态。否则报错
    get操作
    会直接发出sql语句,进行查询,封装进po对象,并放入一级缓存。
    load只有在查询id以外的时候才会发出sql语句查询hibernate返回对象,即其他属性信息也会返回,并放入一级缓存。
    load是延迟加载,如果用get和load获取不存在的对象,get为null,而load报错。因为load是在对象存在的时候在内存中生成代理对象。
    缓存只能被当前事务访问,每个事务有自己的缓存,缓存是用户无法修改的。只能hibernate自己管理,缓存的生命周期与事务同在。事务范围的缓存使用内存作为媒介存储。
    session的刷新有三种情况,执行query,flush,还有事务的提交commit。只有提交时会进行数据库的同步。
    hibernate的update语句到达刷新点后就跟快照内容不一样会发出sql语句,如果一样则不发送sql语句。

3、快照

    session的刷新是指,session缓存中数据的更新。session的同步是指,将session缓存中的数据同步更新到DB中。执行同步的时间点只有一个:事务的提交。

       快照就是数据库的一个镜像。

       缓存刷新模式,即缓存刷新时间点。当这三个刷新时间点到来时,是否会刷新缓存数据,决定于刷新缓存模式的设置。通过session的setFlushMode()方法,可以设置缓存刷新模式。

    用户可以更改一级缓存(PO对象的属性值),但无法手动更改快照!

    快照的主要能力(作用)是:用来更新数据!当刷出缓存的时候,如果一级缓存和快照不一致,则更新数据库数据。

    快照可以用来更新部分数据,而update更新的时候,会将所有值都更新,如果有某个属性没有赋值,值将会被置空。

    快照符合我们修改的要求:先查后改

    刷出缓存:将一级缓存的数据同步到数据库就叫刷出缓存。

    

        

Hibernate的二级缓存

    1、二级缓存是SessionFactory级的缓存,其生命周期与SessionFactory一致。SessionFactory缓存可以依据功能和目的分为内置缓存和外置缓存。

SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的副本。而预定义SQL语句是在HIbernate初始化阶段根据映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置 SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。

    SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库的副本,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的二级缓存。

    Hibernate本身只提供了二级缓存的规范,但并未实现,故需要第三方缓存产品的支持。常用的二级缓存第三方插件有:

    EHCache、Memcached、OSCache、SwarmCache、JBossCache等。这些插件的功能各有侧重,各有特点。

    

2、Hibernate缓存执行顺序

    当Hibernate根据ID访问数据对象时,首先会从一级缓存Session中查找。若查找不到且配置了二级缓存,则会从二级缓存中查找;若还查不到,就会查询数据库,把结果按照ID放入到缓存中。

    执行增、删、改操作时,会同步更新缓存。

(3)二级缓存内容分类

    分局缓存内容的不同,可以将Hibernate二级缓存分为三类:

    (1)类缓存:缓存对象为实体类对象

    (2)集合缓存:缓存对象为集合对象

    (3)查询缓存:缓存对象为查询结果

  二级缓存中的数据对于所有事务来说是共享的。若每个事务都具有读写权限则容易发生脏读。因此二级缓存一般都设置成为read-only。EHCache二级缓存是只读的。

   二级缓存中的类缓存缓存的是类的值,集合缓存缓存的是ID,而query缓存的是sql语句和value。

  如果用query.executeUpdate将修改二级缓存中的时间戳,将会使程序直接从DB中查找而不是从缓存中查。

 

    二级缓存中的集合缓存,存放的是集合的id而不是详情,详情存放在类缓存中。

    一级缓存和二级缓存找那个存id。而query缓存存放的内容,其从query缓存中查找的依据不再是查询结果对象的id,而是query查询语句。是根据语句来查的,也就是说query查询结果存档的缓存时,其key为query的查询语句,value为查询结果。

    根据查询语句来存的,不是根据id,因此from where id=和where id in所得的结果是不同的

    查询语句为key查询结果为value。

 

posted @ 2018-01-03 10:39  张小铁  阅读(251)  评论(0编辑  收藏  举报