zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    TextBox 只有下划线
    can't find web control library(web控件库)
    DropDownListSalesAC”有一个无效 SelectedValue,因为它不在项目列表中。
    IDE、SATA、SCSI、SAS、FC、SSD 硬盘类型
    如何打印1px表格
    CSS控制打印 分页
    Virtual Server could not open its emulated Ethernet switch driver. To fix this problem, reenable the Virtual Server Emulated Et
    Xml中SelectSingleNode方法中的xpath用法
    热带水果莫入冰箱?水果存放冰箱大法
    探索Asp.net的Postback机制
  • 原文地址:https://www.cnblogs.com/fps2tao/p/14183042.html
Copyright © 2011-2022 走看看