zoukankan      html  css  js  c++  java
  • Hibernate(四)之对象状态及一级缓存

    一、Hibernate中的对象状态

      1.1、瞬时态(临时态)

        没有与Hibernate产生关联

        与数据库中的记录没有产生关联(有关联就是与数据库中表的id相对应)   

          获得:一般都只直接创建(new)
          瞬时态 转换 持久态
            一般操作:save方法、saveOrUpdate
          瞬时态 转换 脱管态
            一般操作:通过setId方法设置数据

       1.2、持久态

        Hibernate有关联

        对象有id

          获得:
            查询操作:get、loat、createQuery、createCriteria 等 获得都是持久态【】
            执行save之后持久态
            执行update之后持久态
          持久态 转换 瞬时态
            官方规定执行delete() --民间:删除态
          持久态 转换 脱管态
            session没有记录
            session.close () 关闭
            session.clear() 清除所有
            session.evict(obj) 清除指定的PO对象

      1.3、游离态(脱管态)

        没有与Hibernate产生关联

        对象有ID

          获得:
            创建、并设置OID的
            通过api获得
          脱管态 转换 瞬时态
            手动去除OID,设置成默认值
          脱管态 转换 持久态
            一般操作:update()、saveOrUpdate

      1.4、在代码中去查看三种状态

        

      1.5、三种状态的相互转换

        1.5.1、瞬时转化为持久

        

          注意:如果主键生成策略中value是assigned需要自己指定主键,不指定会报错。

        1.5.2、瞬时转化为游离  

            在数据库中id=1中已经存在有

            

            

        1.5.3、持久转化为瞬时

          

          方式二:

              

        1.5.4、持久转化为游离

          

        1.5.5、游离转化为瞬时

          

        1.5.6、游离转化为持久

          

      1.6、三种状态有什么用处?

        持久状态,我们使用Hibernate主要是为了持久化我们的数据.

        对于对象的状态,我们期望我们需要同步到数据库的数据,都被装换成持久状态

        持久化状态特点: Hibernate会自动将持久化状态对象的变化同步到数据库中.  

        

    二、一级缓存

        又称为session级别的缓存。当获得一次会话(session),hibernate在session中创建多个集合(map),用于存放操作数据(PO对象),为程序优化服务,

        如果之后需要相应的数据,hibernate优先从session缓存中获取,如果有就使用;如果没有再查询数据库。当session关闭时,一级缓存销毁。

      在Hibernate中存在两种缓存:一是线程级别的缓存(session缓存)二是进程级别的缓存(二级缓存)

      缓存:用来提高效率的

        session缓存:就是session对象中存在的缓存,缓存中存在的是(持久化)对象。

      2.1、证明session缓存的存在

        

        我们用图形来理解:

          

      2.2、一级缓存快照

            在从数据库取数据时,会将数据一式两份,一份作为缓存中的对象,一份作为快照,在session提交时做对比。

          快照:与一级缓存一样的存放位置,对一级缓存数据备份。保证数据库的数据与 一级缓存的数据必须一致。如果一级缓存修改了,

              在执行commit提交时,将自动刷新一级缓存,执行update语句,将一级缓存的数据更新到数据库。

            

              

        举例:

          

        我们画图来分析一下: 

              

            

          持久化状态: 本质就是存在缓存中的对象,就是持久化状态.

      2.3、感受一级缓存带来的效率

          感受一:

        

          从上面这三行代码中,我们u1执行需要执行一条sql语句,我们执行得到u2和u3时,发现不会去再次查询,而是从缓存中找。

          感受二:

            

            从上面代码还在那个我们知道,第一个u1中会执行select语句。当事务还没有提交的时候,只会在缓存中进行。

            所以总的只会产生两条sql语句。

      2.4、一级缓存中的细节问题

        问题一:保存对象时,可以使用save方法和persist方法,他们之间有区别吗?

            没有区别,功能上是一样的。但persist(持久) 方法 来自于JPA 接口。而save(保存) 方法来自于Hibernate。

        问题二:HQL查询是否会使用一级缓存?

            HQL不会使用一级缓存.

        

        问题三:HQL语句批量查询时,查询结果是否会进入缓存?

            查询结果会放入缓存中

        

        问题四:SQL查询 结果会不会放入1级缓存中?

            如果把查询结果封装到对象中,对象会放入一级缓存

          

        问题五:SQL查询 结果会不会放入1级缓存中?

            没有把查询结果封装到对象中,对象不会放入一级缓存

              

        问题六:criteria  会将查询结果放入一级缓存. 但是查询不会使用一级缓存. 与Hql查询结论一致.    

    三、session中的其他API

        evict()方法:将缓存中的对象删除

        clear()方法:清空一级缓存

        refresh方法:刷新,强制刷新缓存中的对象 => (可以用来解决缓存与数据库数据不同步的问题)

        

        flush方法:对比快照,并提交缓存对象

    import java.util.List;
    
    import org.hibernate.Session;
    import org.junit.Test;
    
    import com.itheima.domain.User;
    import com.itheima.utils.HibernateUtils;
    //其他API (大部分都是了解)
    public class Demo1 {
        @Test
        //1. evict 将缓存中的对象移除.
        //2. clear 清空1级缓存 
        public void fun1(){
            Session session = HibernateUtils.openSession();
            session.beginTransaction();
            //------------------------------------------------
            User u1 = (User) session.get(User.class, 1);
            
            session.clear();
            
            User u2 = (User) session.get(User.class, 1);
            
            //------------------------------------------------
            session.getTransaction().commit();
            session.close(); // 游离状态
        }
        @Test
        //3 refresh 刷新 => 强制刷新缓存中的对象 => (可以用来解决缓存与数据库数据不同步的问题)
        public void fun2(){
            Session session = HibernateUtils.openSession();
            session.beginTransaction();
            //------------------------------------------------
            User u1 = (User) session.get(User.class, 1);
            
            session.refresh(u1); //将缓存中的对象立刻与数据库同步,会再发送一个sql语句
            //------------------------------------------------
            session.getTransaction().commit();
            session.close(); // 游离状态
        }
        @Test
        //4 flush 对比快照,并提交缓存对象
        public void fun3(){
            Session session = HibernateUtils.openSession();
            session.beginTransaction();
            //------------------------------------------------
            User u1 = (User) session.get(User.class, 1);
            
            //u1.setName("zhangsan");
            
            session.flush();// 立刻提交session缓存中的对象到数据库
            
            //------------------------------------------------
            session.getTransaction().commit();
            session.close(); // 游离状态
        }
        
        @Test
        // 代理主键=> native
        //5.1 aveOrUpdate方法
        //saveOrUpdate 可以同时完成保存或更新操作
        //主键为空=>save
        //主键有值=> update
        public void fun4(){
            Session session = HibernateUtils.openSession();
            session.beginTransaction();
            //------------------------------------------------
            User u = new User();
            u.setId(99);
            u.setName("jack");
            u.setPassword("1234");
            
            session.saveOrUpdate(u);
            //------------------------------------------------
            session.getTransaction().commit();
            session.close(); // 游离状态
        }
        
        // 自然主键=> assigned
        //5 update 与 saveOrUpdate方法
            //saveOrUpdate 可以同时完成保存或更新操作
            //主键为空=> 报错,因为无论是save还是update 都必须指定id
            //主键有值=> 先会根据主键查询数据库.
                    // 数据库中存在=> 执行update
                    // 数据库中不存在=> 执行insert
        @Test
            public void fun5(){
                Session session = HibernateUtils.openSession();
                session.beginTransaction();
                //------------------------------------------------
                User u = new User();
                u.setId(88);
                u.setName("jack01");
                u.setPassword("1234");
                
                session.saveOrUpdate(u);
                //------------------------------------------------
                session.getTransaction().commit();
                session.close(); // 游离状态
            }
        
        
        @Test
        //在我们使用Hibernate时候,注意要避免出现,两个相同的ID对象.放入一级缓存的情况.
        public void fun6(){
            Session session = HibernateUtils.openSession();
            session.beginTransaction();
            //------------------------------------------------
            User u = (User) session.get(User.class, 1);// 持久化,缓存中存在
            
            session.evict(u); // 游离态,缓存中不存在
            
            User u2 = (User) session.get(User.class, 1);// 持久化,缓存中存在
            
            session.update(u); // 将U重新变为持久化状态,缓存中存在
            //------------------------------------------------
            session.getTransaction().commit();
            session.close(); // 游离状态
        }
    }
    testSessionApi

      

      

        

        

        

        

      

        

          

        

        

        

  • 相关阅读:
    Android控制软键盘的现实与隐藏
    Android调用手机浏览器
    DatePicker隐藏年/月/日
    ecplise中设置字符编码
    Git问题总结
    Git的简单使用
    资源
    equals和==
    class文件查看
    Class file collision
  • 原文地址:https://www.cnblogs.com/cxyzyh2017/p/6678517.html
Copyright © 2011-2022 走看看