Hibernate的一级缓存

一、hibernate的持久化对象
hibernate缓存首先需要理解hibernate的持久化对象:
1. 持久化对象有三种状态:
(1)transient(瞬时态):尚未与Session关联对象,失去引用的话,就会被JVM回收。一般就是直接New创建的对象。
(2) persistent(持久态):已经与当前session产生关联,并且相关联的session没有关闭,并且事务尚未提交。
(3) detached(脱管态):存在持久化OID,但没有与当前session关联,脱管状态改变hibernate不能检测到。  

  1. 相关代码
 Session session = HibernateUtils.openSession();        // 获得session

 Transaction transaction = session.beginTransaction();  // 开启事务 

 Book book = new Book(); // 瞬时态(没有OID,未与Session关联)  
 book.setName("hibernate从入门到精通");  
 book.setPrice(32d);  

 session.save(book);     // 持久态(具有OID,与Session关联)  

 transaction.commit();   // 提交事务,关闭Session 
 session.close();        // 关闭Session 

 System.out.println(book.getId()); // 脱管态(具有 OID,与Session断开关联)  
  1. 持久化对象之间转变
    (1)瞬态对象——通过new关键字获取
    瞬时——持久:save、saveOrUpdate(都是通过session获得)
    瞬时——脱管:对象.setID(1);为瞬时对象设置新的OID
    (2)持久化对象——通过get/load、Query查询获得
    持久——瞬时:delete(被删除持久化对象,不建议再次使用)
    持久——脱管:evict(清楚一级缓存中某个对象)、close(关闭Session,清除一级缓存)、clear(清楚一级缓存所有对象)
    (3)脱管对象:无法直接获得
    脱管——瞬时:对象.setID(null);删除对象OID
    脱管——持久:update、saveOrUpdate、lock

二、hibernate一级缓存

  1. 使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率;

  2. Hibernate中的一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数,只在session范围内有效,session关闭,一级缓存失败;

    Session 级别的缓存,它同session邦定。它的生命周期和session相同。Session消毁,它也同时消毁;管理一级缓存,一级缓存无法取消,用两个方法管理,clear(),evict()

  3. 一级缓存的特点,只在session范围有效,作用时间短,效果不是特别明显,在短时间内多次操作数据库,效果比较明显。

  4. 当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session缓存中;

  5. session的缓存是由hibernate维护的,用户不能操作缓存内容;如果想操作缓存内容,必须通过hibernate提供的evict/clear方法操作

  6. 不同的session是不会共享缓存数据的

    两个session 不能共享一级缓存,因它会伴随session的生命周期的创建和消毁;

  7. Session缓存是实体级别的缓存,就是只有在查询对象级别的时候才使用,如果使用HQL和SQL是查询属性级别的,是不使用一级缓存的!切记!!!!

  8. iterate 查询使用缓存,会发出查询Id的SQL和HQL语句,但不会发出查实体的,它查询完会把相应的实体放到缓存里边,一些实体查询如果缓存里边有,就从缓存中查询,但还是会发出查询id的SQL和HQL语句。如果缓存中没有它会数据库中查询,然后将查询到的实体一个一个放到缓存中去,所以会有N+1问题出现。

    list和iterator的区别?

        list:一次性把所有的记录都查询出来了;

          会放入缓存,不会从缓存中取数据

        iterator:N+1次查询,

             N表示所有的记录总数,即会发送一条语句查询所有的记录的主键(1),再根据每一个主键取数据库查询N;

             会放入缓存,也会从缓存中取出数据;
            

  9. 缓存相关的方法:

        session.flush();让一级缓存与数据库同步;

        session.evict();清空一级缓存中指定的对象;

        session.clear();清空一级缓存中所有的对象;

常见的操作

1.flush
修改一级缓存数据,针对内存操作,需要在session执行flush操作时,将缓存变化同步在数据库,而只有在缓存数据与快照区不一致的时候,才会生成update语句。

public void fun7() {  
    // 通过工具类获取session值  
    Session session = HibernateUtils.getSession();  
    // 启动事务操作  
    session.beginTransaction();  

    // session.setFlushMode(FlushMode.MANUAL);  

    // 通过ID从数据库中获取值,此时会产生快照  
    Book book1 = (Book) session.get(Book.class, 1);  
    // 修改属性值  
    book1.setName("struts");  
    // 手动flush,刷新缓存到数据库,此时只是生成SQL语句,但是数据库中并没有发生变化,只有commit后,数据库才会发生相应的变化。  
    session.flush();  
    // 手动提交事务  
    session.getTransaction().commit();  
    // 关闭session的资源  
    session.close();  
}

3.evict
清空一级缓存中指定的对象

    @Test  
    public void fun5() {  

        Session session = HibernateUtils.getSession();  

        session.beginTransaction();  

        //当执行一次操作后,会把对象放置到Session缓存中  
        Book book1 = (Book) session.get(Book.class, 1);  
        Book book2 = (Book) session.get(Book.class, 2);  



        session.evict(book2); // 从缓存中清楚book2对象所做的修改  
        // 当再次执行操作时,book2还会发出SQL语句操作  
        Book book11 = (Book) session.get(Book.class, 1);   
        Book book22 = (Book) session.get(Book.class, 2);  

        // 手动提交事务  
        session.getTransaction().commit();  
        // 关闭资源  
        session.close();  
    }

3.clear
清除所有对象的一级缓存,对对象所做的修改,全部都没有了,跟当初的快照一样。

public void fun7() {  
        // 通过工具类获取session值  
        Session session = HibernateUtils.getSession();  
        // 启动事务操作  
        session.beginTransaction();  

        // session.setFlushMode(FlushMode.MANUAL);  

        // 通过ID从数据库中获取值,此时会产生快照  
        Book book1 = (Book) session.get(Book.class, 1);  
        // 修改属性值  
        book1.setName("struts");  
        //清除一级缓存操作,此时当作事务提交的时候,数据库中并没有发生任何的变化  
        session.clear();  
        // 手动提交事务  
        session.getTransaction().commit();  
        // 关闭session的资源  
        session.close();  
    }  

4.refresh
重新查询数据库,更新快照和一级缓存

    @Test  
    public void fun6() {  

        Session session = HibernateUtils.getSession();  

        session.beginTransaction();  

        // 从数据库中查询book,并放置到Session缓存中一份  

        Book book1 = (Book) session.get(Book.class, 1);   
        //修改缓存对象的值  
        book1.setName("spring");   

        //又进行了一次查询操作,此时把快照中的数据与数据库一致  
        session.refresh(book1);  

        System.out.println(book1);  

        // 手动提交事务 
        session.getTransaction().commit();  
        // 关闭session的资源 
        session.close();  
    }

5.Session手动控制缓存
在hibernate中也为 我们提供了手动控制缓存的机制,具体如下
Always:每次查询时,session都会flush
Auto:有些查询时,session会默认flush,例如commit。session.flush
Commit:在事务提交的时候
Manual:只有手动调用sessionflush才会刷出

public void fun7() {  
        // 通过工具类获取session值  
        Session session = HibernateUtils.getSession();  
        // 启动事务操作  
        session.beginTransaction();  

         session.setFlushMode(FlushMode.MANUAL);  

        // 通过ID从数据库中获取值,此时会产生快照  
        Book book1 = (Book) session.get(Book.class, 1);  
        // 修改属性值  
        book1.setName("struts");  
        //因为上面开启了,手动提交缓存,所以只有手动提交,才能同步到数据库操作  
        session.flush();  
        // 手动提交事务  
        session.getTransaction().commit();  
        // 关闭session的资源  
        session.close();  
    }  

分析:hibernate向一级缓存放入数据时,同时保存快照数据,当修改一级缓存的时候,在flush操作时,对比缓存和快照,如果不一致,自动更新。

以上内容是对 http://blog.youkuaiyun.com/luckyzhoustar/article/details/47665495
http://www.cnblogs.com/biehongli/p/6596700.html 的整合,便于日后翻看,非原创

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值