zoukankan      html  css  js  c++  java
  • Hibernate-Session使用的背后

    一、Session缓存的介绍

      简单说,缓存介于应用程序和数据库之间,是临时存放数据的内存区域,作用是减少对数据库的访问次数,从而提高应用程序的运行性能。Session有一个缓存,也叫hibernate的一级缓存,Hibernate查询数据的时候,首先到session缓存中看看有没有,有的话直接拿来使用,没有的话,才去访问数据库读取数据。

      众所周知,一个java对象如果没有被任何变量引用的话,就会被GC自动回收,生命周期结束。Session接口的实现中包含一系列的java集合,这些java集合构成了session的缓存。也就是说,Session持有这些java对象的引用,所以只要session实例没有结束生命周期,存放在它缓存中的对象也不会结束生命周期。

    二、Session的清理缓存和脏检查机制

      清理缓存:session会在某些时间点根据缓存的对象数据的变化来执行相关的sql语句,来同步更新数据库。

      脏检查:当一个java对象加载到session缓存中,Session会为该对象的值类型属性复制一份快照。当session清理缓存的时候,会将对象目前的值与它的快照相比较,若有变化,这个对象便称为“脏对象”,session会根据脏对象最新的值来执行相关的sql语句。

      下面来看一个小例子:

        Session session = sessionFactory.openSession();
        User user = (User) session.get(User.class, 1l);
        user.setPassword("123"); //起初数据库password值为null
        session.close(); //session关闭后,数据库password值仍为null 
        //另一种情况:
        Session session2 = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        User user2 = (User) session.get(User.class, 1l);
        user2.setPassword("123"); //起初数据库password值为null
        tx.commit();
        session.close(); //session关闭后,数据库password值变为'123'

    首先,如果不开启事务的话,利用session的get方法从数据库读取得到一个对象,然后修改该对象的值,session缓存中的对象属性值改变了,但数据库的值不会改变(发出一条sql查询语句);在开启事务的情况下,修改该对象的值,然后提交事务,数据库中对应的值会改变(发出两条sql语句,一条查询一条更新)。Why?

      因为,在默认情况下,session会在以下时间点清理缓存:

      a)调用transaction的commit()方法时,先清理缓存再提交事务;

      b)显式调用session的flush()方法时;

      c)应用程序执行一些查询操作,涉及到缓存中其属性值已经改变的对象。

      session的关闭并不会自动清理缓存,进行脏检查。不过,我们使用session更新保存对象的时候,一般会开启事务,在提交事务的时候,session便会清理缓存了,并且会释放session占用的数据库连接。要想理解session各方法,就应该知道hibernate什么时候会向数据库发出SQL语句,发出多少条怎样的SQL语句。

    三、Session主要方法的介绍

      简略谈谈各方法之前,得说说java对象在hibernate持久化的状态:

      a)临时状态:刚new出来,不存在数据库中(没被持久化),不存在session缓存中;

      b)持久化状态:存在数据库中(已被持久化),存在session缓存中;

      c)游离状态:存在数据库中(已被持久化),但不存在session缓存中;

      d)删除状态:不再存在session缓存中,且session已计划将其从数据库中删除。

    1)save()方法:如果对象使用native生成器生成OID的话,会马上发出一条insert语句,我们便可通过getId()得到该对象的id。对临时对象save完后,再save的话无效(仅发出1条insert语句);对游离状态多次save的话,则会保存多条重复记录(会发出多条insert语句)。

    2)load()和get()方法:
    load()使用延迟检索策略,不存在该记录时,抛出异常 (调用load的时候等到需要查询其属性再发出select语句,否则不发出select语句);
    get()使用立即检索策略,不存在某条记录时,返回null(调用get的时候会立即发出select语句)。

    3)update()方法:将游离状态的对象转换为持久化状态,保存到数据库(发出一条update语句)。在清理缓存之前,即使该对象属性值改变多次,session也只是最后才发出执行一次sql语句。

    4)saveOrUpdate()方法:判断对象是游离状态还是临时状态,然后发出insert或者update语句。

    5)delete()方法:session在清理缓存的时候才发出delete语句,一次只能删除一个对象。

    四、Session的获取与管理

      1,sessionFactory.openSession(),需要手动关闭session;

      2,若hibernate与spring整合后,需要配置加入spring提供的事务管理机制,例如加上@Transactional,才能通过sessionFactory.getCurrentSession()获取当前线程绑定的Session,之后无须手动关闭session。简单来说,Spring的Session总是与某个线程绑定的,而这个线程往往就是承载Servlet或Jsp的那个线程,也就是说,它的生命周期scope是request的,线程结束之前,与线程绑定的session会自动被关闭。

    最后,以上仅供参考,有何地方出错,欢迎拍砖指正。

  • 相关阅读:
    JavaEE 第四周
    JavaEE 第三周
    JavaEE 第二周
    JavaEE 第一周
    js字符串方法
    javaee项目库存管理系统总结
    javaee期末团队项目库存管理系统概要信息
    JAVAEE第十一周
    JSON
    Facelets
  • 原文地址:https://www.cnblogs.com/jianzhi/p/3406022.html
Copyright © 2011-2022 走看看