• SSH学习-Hibernate缓存机制&懒惰加载


    Hibernate查询会先从一级缓存session中查询数据,如果session中没有会从sessionfactory中查找数据,如果前面两个都没有将从DB中查数据,这就是Hibernate的缓存机制,这样可以降低应用程序与物理数据源的交互频率,提高应用程序的性能。另外懒惰加载,就是尽可能晚的将数据库中的数据加载到内存中来,需要查询时查询数据,不需要查询的数据暂时就不查询。

    一级缓存session管理方法

    (1)evict(Object):将对象Object从session中清除掉,从持久状态进入到游离状态

    (2)clear():将session中的所有对象都清除掉

    (3)flush():将缓存中的数据与数据库中的数据进行同步

    (4)contains(Object):判断session中是否包含某个对象Object

    6)将保存的数据放到session:save()

    7)将查询的数据放到sessionget(),load(),HQL查询

    下面以一个案例进行分析,先使用get方法到一个对象存到session中,然后再重复一遍get动作,比较两个对象是否相同,如果相同说明第二次是从缓存中取出。

    具体的hibernate.cfg.xml,表和实体类参考上一篇博客,这里直接调用测试方法进行测试,看看两次get得到的对象是否是同一个内存地址,如果是true说明就是同一对象。

    package TestCase;
    
    import java.util.List;
    import java.util.Set;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.Test;
    
    import Entity.book;
    import Entity.user;
    
    /**
     * 测试Hibernate关联查询
     * @author yangchaolin
     */
    public class testHibernate {
        
          public static Session getSession() {
              //读取hibernate.cfg.xml配置文件
              Configuration cfg=new Configuration();
              cfg.configure("hibernate.cfg.xml");
              //创建sessionfactory
              SessionFactory factory=cfg.buildSessionFactory();
              //创建session
              Session session=factory.openSession();
              return session;
          }
          
          //测试session缓存机制
          @Test
          public void testSession() {
              //获取session
              Session session=getSession();
              //开启事务
              Transaction trans=session.beginTransaction();
              trans.begin(); 
              //执行持久层操作
              user u1=(user) session.get(user.class, 1);//查询id为1的user
              //提交事务
              //trans.commit();          
              //重复获取user对象的操作
              user u2=(user) session.get(user.class, 1);
              System.out.println("两个是否相同"+(u1==u2));
              /**
               * 测试发现结果为true,说明二次取得是保存在session中的数据
               */
              //关闭session
              session.close();
          }    
    }

    测试结果

    从测试结果来看,第二次获取是从session一级缓存中获取的,并不是从DB中取出新存到内存中的对象,两者内存地址一致,输出结果为true。

    懒惰加载

    参考获取user为1的数据后,先打印user的id和name属性,后面再打印user的book属性,控制台发现先查询得到user 的id和name,当后面需要输出book时,再从数据库查询book,说明数据查询分了2次,不是一次性查询得到,这种现象就是懒惰加载。

    映射文件中配置lazy属性到set标签下

          <!-- lazy设置为false,代表不懒惰加载,默认是懒惰加载 -->
          <set name="books" lazy="true"><!-- 实体类对应属性名 -->
            <key column="user_id"></key>
            <one-to-many class="Entity.book"></one-to-many>
          </set>
    package TestCase;
    
    import java.util.List;
    import java.util.Set;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.Test;
    
    import Entity.book;
    import Entity.user;
    
    /**
     * 测试Hibernate关联查询
     * @author yangchaolin
     *
     */
    public class testHibernate {
        
          public static Session getSession() {
              //读取hibernate.cfg.xml配置文件
              Configuration cfg=new Configuration();
              cfg.configure("hibernate.cfg.xml");
              //创建sessionfactory
              SessionFactory factory=cfg.buildSessionFactory();
              //创建session
              Session session=factory.openSession();
              return session;
          }
    
          //测试获取user id为1的用户的信息
          @Test
          public void test() {
              //读取hibernate.cfg.xml配置文件
              Configuration cfg=new Configuration();
              cfg.configure("hibernate.cfg.xml");
              //创建sessionfactory
              SessionFactory factory=cfg.buildSessionFactory();
              //创建session
              Session session=factory.openSession();
              //创建一个事务并开启事务
              Transaction trans=session.getTransaction();
              trans.begin();
              //开始执行持久层操作
              user user=(user) session.get(user.class, 1);//1代表user的id属性值
              System.out.println(user.getId());
              System.out.println(user.getName());
              Set<book> books=user.getBooks();
              for(book book:books) {
                  System.out.println(book);
              }
              //关闭session
              session.close();
          }      
        
    }

    打印结果

    当将set标签下lazy设置为true,可以看出来先查询出来id和name,当需要打印book时,才查询books属性,它的查询分了两次,这就是懒惰加载,你不需要我不加载你需要时我再加载。

    现在有个问题,如果第二次查询时,session提前关闭了会怎么样?结果是第二次将查询不到数据,为了避免因为懒惰加载和session提前关闭对查询结果的影响,struts2中有一个filter(OpenSessionInViewFilter)专门用于提前开启session,避免因为session提前关闭查询不到数据的情况,后面有机会再了解。

    结论

    Hibernate下无论是缓存机制还是懒惰加载,都是为了提高性能,因为其减少了应用程序对数据源的访问。

  • 相关阅读:
    javaScript类型和对象
    极客时间买课全额返现
    极客时间返利课程返利文字版
    负责范围
    list查询
    缺件修改
    修改信息
    Windows系统解决占用端口问题
    mysql系列——常用的几十个函数详解(六)
    史上最全日期时间类讲解
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/10909771.html
Copyright © 2020-2023  润新知