美文网首页
Hibernate Session

Hibernate Session

作者: BlueSkyBlue | 来源:发表于2020-03-22 17:17 被阅读0次

    Session接口是Hibernate向应用程序提供的操纵数据库的主要接口,它提供了基本的保存,更新,删除和加载Java对象的方法。

    Session具有一个具体的缓存,位于缓存中的对象称为持久化对象。它和数据库中的记录对应。Session可以在某些时间点,按照缓存中的对象变化来执行相应的SQL语句,同步更新数据库,这一过程称为刷新缓存(flush)。

    站在持久化的角度将Hibernate分为四种状态:

    • 持久化状态
    • 临时状态
    • 游离状态
    • 删除状态

    Session中的特定方法能使对象从一个状态转为另一个状态。

    Session缓存

    在Session接口的实现中包含了一系列的Java集合,这些Java集合构成了Session缓存。只要Session实例没有结束生命周期,且没有清理缓存。则存放在它缓存的对象也不会结束生命周期。

    Session缓存可以减少Hibernate应用程序访问数据库的次数。

    HelloWorld helloWorld = this.session.get(HelloWorld.class, 1);
    HelloWorld helloWorld2 = this.session.get(HelloWorld.class, 1);
    

    这两条查询只会使用一次SQL语句。


    HelloWorld helloWorld = session.get(HelloWorld.class, 1);
    helloWorld.setTitle("Today");
    

    当我们使用set方法是自动更新到了数据库。查看控制台我们会发现程序实际上调用了SQL语句。此时会自动调用flush方法。

    flush缓存

    flush的作用:使数据库中的对象与Session中的对象保持一致。为了保持一致,则可能发送SQL语句。

    在调用commit方法时,会先进行flush,然后再提交事务。

    在Transaction的commit方法中,先调用session的flush方法,再提交事务。

    flush方法可能会发送SQL语句。不会提交事务。

    注意:在未提交事务或者显示的调用session.flush()方法之前,也有可能会进行flush操作。

    1. 执行HQL或者QBC查询。会先进行flush操作,得到数据表最新的记录。
    2. 若数据记录的ID是由底层数据库使用自增的方式生成的,则在调用save方法后就会立即发送insert语句。因为save方法必须保证对象的ID是存在的。

    commit和flush方法的区别:flush执行一系列的SQL语句,但不提交事务。commit方法会先调用flush方法,然后提交事务。意味着提交事务那么数据库操作就被永久的保存下来。

    refresh

    缓存中的数据是最新的状态。调用这个方法会强制发送一条select语句得到记录的最新状态。

    refresh会强制发送select语句,使session缓存中的对象的状态和数据表中对应的记录保持一致。

    操作Session缓存

    持久化对象

    • 临时对象(Transient)
      在使用代理主键的情况下,OID通常为null。
      不处于Session缓存中。
      在数据库中没有对应的记录。

    • 持久化对象(Persist)
      持久化对象也叫托管。
      OID不为null。
      位于Session缓存中。
      若在数据库中已经有和其对应的记录,持久化对象和数据库中相关的记录对应。
      Session在flush缓存时,会根据持久化对象的属性变化,来同步更新数据库。
      在同一个Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象。

    • 删除对象(Removed)
      在数据库中没有和其OID对应的记录。
      不再处于Session的缓存中。
      一般情况下,应用程序不该再使用被删除的对象。

    • 游离对象(Detached)
      也叫托管。
      OID不为null。
      不再处于Session缓存中。
      一般情况下,游离对象是从持久化对象转变过来的。因此在数据库中可能还存在与它对应的记录。

      对象状态转换图

    Session持久化操作的方法

    首先说一个概念OID。Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系。当News对象处于持久化状态时,不允许程序随意修改它的Id

    save()方法:

    1. 使一个临时对象变为一个持久化对象。
    2. 为对象分配Id。
    3. 在flush缓存时会发送一条insert语句。
    4. 在save方法之前的Id是无效的。
    5. 持久化对象的Id是不能被修改的。

    persist()方法:

    1. 也会执行insert操作。
    2. 如果在persist方法之前有Id了,则不会执行insert操作,而是抛出一个异常。

    get和load的区别:

    1. 执行get方法会立即加载对象,而执行load方法,若不使用该对象。则不会立即执行查询操作,而返回一个代理对象。get立即查询。load延迟加载。
    2. 如果在数据库中没有对应的记录。Session没有被关闭,同时需要使用对象时,get会返回一个空值(null),load则会抛出一个异常。
    3. load方法可能会抛出懒加载异常(LazyInitializationException)。在需要初始化代理对象之前已经关闭了Session。

    update方法:

    1. 若更新一个持久化对象,则不需要显式的调用update方法。因为在调用transaction的commit方法时会先执行Session的flush方法。
    2. 更新一个游离对象时,需要显示的调用Session的update方法。同时可以将一个游离对象变为一个持久化对象。

    注意:

    1. 无论要更新的游离对象与数据包中的记录是否一致,都会发送Update语句。
      如何让update方法不盲目的触发Update语句:
      在*.hbm.xml文件的class结点设置一个属性select-before-update=true。通常不需要设置该属性。

    2. 若数据表中没有对应的记录,但还是调用了update方法则会抛出异常。

    3. 若在Session缓存中存在相同的OID的持久化对象,则会抛出异常。因为在同一个Session的缓存中不能有两个Id相同的对象。

    saveOrUpdate方法:

    saveOrUpdate方法同时包含了save方法和update方法的功能。



    判定对象为临时对象的标准:

    • Java对象的OID是否为null。
    • 映射文件中<id>设置了unsaved-value属性。并且Java对象的OID取值和这个unsaved-value属性相匹配。

    若OID不为空,但数据表中还没有和其对应的记录,会抛出一个异常。
    OID的值等于ID的unsaved-value属性值的对象,也被认为是一个游离对象。

    delete方法

    执行删除操作。只要OID和数据表中的一条记录对应,就会执行delete操作。如果没有对应的记录则抛出异常。

    可以通过设置Hibernate配置文件的属性hibernate.use_identifier_rollback为true使删除对象后把其OID置为null。

    evict方法

    从Session缓存中把指定的持久化对象移除。

    通过Hibernate调用存储过程

    Session的doWork(Work)方法用于执行Work对象指定的操作。即调用Work对象的execute方法,Session会把当前使用的数据库连接传递给execute方法。

    Hibernate与触发器协同工作

    Hibernate与触发器协同工作时会造成两个问题:

    1. 触发器使Session缓存中的持久化对象与数据库中对应的数据不一致。触发器在数据库中操作,它执行的操作对于Session是透明的。
    2. Session的update方法盲目的触发触发器。无论游离对象的属性是否发生变化都会执行update语句。而update语句会触发数据库中相应的触发器。

    解决方案

    1. 在执行完Session的相关操作后,立即调用Session的flush和refresh方法。迫使Session缓存和数据库的数据同步。方法重新从数据库中加载数据。
    2. 在映射文件的<class>元素中设置select-before-update属性。当Session的update或saveOrUpdate方法更新一个游离对象时,先执行select语句获取该游离对象在数据库中的最新数据。只有在不一致的情况下才会执行update操作。

    相关文章

      网友评论

          本文标题:Hibernate Session

          本文链接:https://www.haomeiwen.com/subject/ghsmyhtx.html