• hibernate入门(二)一级缓存和三种状态解析


    先理解了hibernate的一级缓存和它的三种状态,才能对后面我要讲解的一对多,一对一、多对多这种映射关系更好的理解.

    目录:

      1.hibernate的缓存和快照(有些说法没有快照概念)

      2.常用的方法理解 

      3.hibernate的三或四种状态

    1. session是有一个缓存,又叫hibernate的一级缓存. session缓存是有一系列java集合构成的,当一个对象被加入到session缓存中,对象的引用就加入到java的集合中, 以后即使应用程序的引用变量中不在引用改对象,只要session缓存不被清空,这个对象一直处于生命周期中.

    hibernate需要和数据库打交道,是通过session获得缓存中的关联对象,然后拼接成相应的sql再执行.

    具体过程:

    1)、首先session将一个对象加入自己的管理范围内,其实也就是把该对象放入自己的一级缓存中。如,session.get(xxx);这个语句就是将xxx保存在自己的一级缓存中,等待事务提交后,hibernate才真正的发sql语句,操作数据库。

    2)、在一级缓存中会做些什么事情呢?为什么能够知道是发insert、还是update又或者delete呢?讲讲内部是什么原理。那这里就要提到一个快照的概念了,讲讲内部是什么原理。

    package com.cc8w;
    
    import java.util.Date;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.cc8w.entity.UserEntity;
    
    /**
     * 主要是hibernate缓存的配置
     * @author Administrator
     * session是有一个缓存,又叫hibernate的一级缓存
     * session缓存是有一系列java集合构成的,当一个对象被加入到session缓存中,对象的引用就加入到java的集合中,
     * 以后即使应用程序的引用变量中不在引用改对象,只要session缓存不被清空,这个对象一直处于声明周期中.
     */
    public class AppTest {
       
        private Configuration configuration=null;
        private SessionFactory sessionFactory=null;
        private Session session=null;
        private Transaction transaction=null;
        
        @Before
        public void beforeTest() {
            System.out.println("beforeTest");
            
            //1. 加载Hibernate的核心配置文件
            configuration = new Configuration().configure();
            //如果在Hibernate的核心配置文件没有设置加载哪个映射文件,则可手动加载映射文件
            //configuration.addResource("com/cc8w/mapper/UserMapper.hbm.xml");
            
            //2. 创建SessionFactory对象,类似于JDBC中的连接池
            sessionFactory = configuration.buildSessionFactory();
            
            //3. 通过SessionFactory获取到Session对象,类似于JDBC中的Connection
            session = sessionFactory.openSession();
            
            //4. 手动开启事务,(最好是手动开启事务)
            transaction = session.beginTransaction();
            
            //5.执行语句写在测试方法里面
        }
        @After
        public void afterTest() {
            System.out.println("afterTest");
            //6. 事务提交
            transaction.commit();    
            //7. 释放资源
            session.close();
            sessionFactory.close();
        }
        
        @Test
        public void TestCache() {
            UserEntity user = new UserEntity();
            user.setCname("123");
            user.setUserName("李123");
            user.setCreateTime(new Date());
            
            session.save(user);//加入了一级缓存中,提交事务时insert操作
            
            user.setCname("789");
            user.setUserName("李789");//将快照区域的属性值修改,和一级缓存对比,不一样将发起update
            /**
             * 在session将user加入一级缓存时,一级缓存和快照区域是一样的,当user改变自己的username属性时,此时将快照区中的user的username属性改变了,
             * 在事务提交时,会发送insert插入语句,因为使用了session的save语句,将一级缓存中的数据增加到数据库,然后再通过快照区和一级缓存做对比,
             * 如果不一样的地方,那么就会在发送一个update语句更新,(注意,除了id属性外,其他属性改变会发送update语句,id属性改变,就会报异常.)
             */
        }
    }

     如果没有快照概念这样理解:

    如果一个对象以及是持久化状态了,那么此时对该对象进行各种修改,或者调用多次update、save方法时,hibernate都不会发送sql语句,只有当事物提交的时候,此时hibernate才会拿当前这个对象与之前保存在session中的持久化对象进行比较,如果不相同就发送一条update的sql语句,否则就不会发送update语句。

     发送的sql语句:

    Hibernate: 
        insert 
        into
            t_admins
            (username, password, cname, email, create_time, last_time) 
        values
            (?, ?, ?, ?, ?, ?)
    
    Hibernate: 
        update
            t_admins 
        set
            username=?,
            password=?,
            cname=?,
            email=?,
            create_time=?,
            last_time=? 
        where
            id=?

     session.get()

        @Test
        public void getUser() {
            //发起select查询,并存到session一级缓存,给快照去复制一份
            UserEntity user = session.get(UserEntity.class,6);
            //修改了快照区,会发出update语句。
            user.setCname("李1112");
            
        }

    分析图

     sql:

    Hibernate: 
        select
            userentity0_.id as id1_0_0_,
            userentity0_.username as username2_0_0_,
            userentity0_.password as password3_0_0_,
            userentity0_.cname as cname4_0_0_,
            userentity0_.email as email5_0_0_,
            userentity0_.create_time as create_t6_0_0_,
            userentity0_.last_time as last_tim7_0_0_ 
        from
            t_admins userentity0_ 
        where
            userentity0_.id=?
    afterTest
    Hibernate: 
        update
            t_admins 
        set
            username=?,
            password=?,
            cname=?,
            email=?,
            create_time=?,
            last_time=? 
        where
            id=?

     2. 通过几个方法来深刻理解下缓存: 

    1) session.evict() :会把指定的缓冲对象进行清除;

    2) session.flush()的作用就是将session的缓存中的数据与数据库同步。(也就是不用事务提交缓存就刷出来了,就会发sql语句,事务提交也是一个刷出缓存的方法,)

    3) session.clear()的作用就是清除session中的缓存数据(不管缓存与数据库的同步)。

    4)session.refresh():会强制发送select语句,以使session缓存中对象的状态和数据表中对应的记录保持一致。该方法的有效性需要配置事务的隔离级别为read commited(读已提交)。

    session.evict()

        @Test
        public void testEvict() {
            //发起select查询,并存到session一级缓存,给快照去复制一份
            UserEntity user = session.get(UserEntity.class,6);
            //将user从session一级缓存中移除(快照区域没删)
            session.evict(user);
            
            //这里不会发送update语句(快照区域和缓存对比,发现无此实例,就什么也不做)
            user.setCname("李1118");
            
        }

     3.     Hibernate 的三种实体状态  (下一篇 )

     Hibernate有三种实体状态,有瞬时态(transiant),持久态(persistent),游离态(detached)。 简单理解就是,瞬时态指的是刚New 新建的一个对象,没有放在Session时,也没有存储在数据库中。 持久态,指这个对象存储在数据库中,并且存在于Session会话中。 而游离态指的是,这个对象存储在数据库中,但已经不存在于Session会话中。下面是比较官方的说法:

    转 参考: https://www.cnblogs.com/whgk/p/6103038.html

     https://www.cnblogs.com/yjhrem/articles/2374818.html

    三种状态的解析: https://blog.csdn.net/yjltx1234csdn/article/details/83214978

  • 相关阅读:
    企业搜索引擎开发之连接器connector(二十九)
    solr&lucene3.6.0源码解析(四)
    solr&lucene3.6.0源码解析(三)
    elasticsearch 7.7.0 最新版+Java High Level REST Client测试
    自制聊天软件测试
    网页正文内容抽取测试
    Kernel Functions for Machine Learning Applications
    Latent semantic analysis note(LSA)
    jQuery插件备忘
    比较成系列的文章[备份.感谢这些作者的辛苦]
  • 原文地址:https://www.cnblogs.com/fps2tao/p/14183042.html
Copyright © 2020-2023  润新知