• Hibernate第二天:Hibernate的一级缓存、其他的API


    Hibernate第二天:Hibernate的一级缓存、其他的API

     

    目录

    Hibernate第二天:Hibernate的一级缓存、其他的API

     

     

     

    1持久化类的编写规则

    1.2持久化类的编写规则

    2主键生成策略

    2.1主键的分类

    2.1.1自然主键

    2.1.2代理主键

    2.2主键生成策略

    3持久化类的三种状态

    3.1持久化类的三种状态

    3.2区分三种状态对象

    3.3持久化类的状态转换(了解)

    3.4持久化类持久态对象自动更新数据库

    4Hibernate的一级缓存

    4.1缓存概述

    4.2Hibernate缓存

    4.2.1Hibernate一级缓存

    4.2.2证明Hibernate一级缓存存在

    4.2.3Hibernate一级缓存结构

    5Hibernate的事务管理

    5.1什么是事务

    5.2事务的特性

    5.3如果不考虑隔离性,引发安全性问题

    5.3读问题的解决

    5.4Hibernate设置事务隔离级别

    5.5Hibernate解决Service的事务管理

    6Hibernate的其他API

    6.1Query

    6.2Criteria

    6.3SQLQuery


     

    1持久化类的编写规则

    1.1什么是持久化类

     

    持久化,将内存中的一个对象持久化到数据库的过程。Hibernate框架就是用来进行持久化的框架。

    持久化类,一个Java对象与数据库表建立了映射关系,那么这个类在Hibernate中称为持久化类。

    持久化类=Java类+映射文件。

     

    1.2持久化类的编写规则

    1. 持久化类提供一个无参的构造方法            Hibernate底层需要使用反射生成实例。
    2. 属性需要私有,对私有属性提供public的set和get方法:Hibernate中获取,设置对象的值。
    3. 对持久化类提供一个唯一的标识OID与数据库主键对应:Java中通过对象的地址区是否是同一个对象,数据库表中通过主键绑定是否是同一个记录,Hibernate中通过持久化类的OID的属性区分是否是同一个对象。
    4. 持久化类中的属性,尽量使用包装类类型:因为基本数据类型默认值是0,会有很多歧义,包装类默认值为NUll
    5. 持久化类不要用使用final进行修饰:延迟加载本身是hibernate一个优化的手段,返回的是一个代理对象(javassist可以对没有实现接口的类产生代理-使用了非常底层的字节码增强技术,继承这个类进行代理),如果不能继承,不能产生代理对象,延迟加载就会失效,load()get()方法一致。

    2主键生成策略

    2.1主键的分类

    2.1.1自然主键

    1. 自然主键,主键的本身就是表中的一个字段(实体中的一个具体属性)。
    1. 创建一个人员表,人员就会有一个身份证号(唯一且不可重复),使用了身份证号作为主键,这种主键称为是自然主键。

     

     

    2.1.2代理主键

    1. 代理主键,主键的本身不是表中必须的一个字段(不是实体中的某个具体属性)。
    1. 创建一个人员表,没有使用人员中的身份证号,用了一个与这个表不相关的字段ID,(PNO)。这种主键称为是代理主键。

    在实际开发中,尽量使用代理主键,因为一旦主键参与到业务逻辑中,后期可能需要修改原代码。好的程序设计满足OCP原则,对程序的扩展是Open的,对修改源码是close的。

     

    2.2主键生成策略

    在实际开发中,一般不允许用户手动设置主键,一般将主键交给数据库,或者手动编写程序进行设置。在Hibernate中为了减少程序编写,提供了很多主键生成策略。

     

    1. Increment :hibernate中提供的自动增长机制,适用short,int,long类型党的主键,在单线程中使用。首先发送一条语句,select id  from 表,然后让id+1作为下一条记录的主键。
    2. Identity:自动增长,适用short,int,long类型的主键,使用的是数据库底层的自动增长,适用于有自动增长机制的数据库(MySQL,MSSQL),Oracle没有自动增长。
    3. Sequence:自动增长,适用short,int,long类型的主键,采用序列方式(Oracle支持序列)。Mysql不能使用。
    4. UUID:适用于字符串类型,使用Hibernate中的随机方式生成字符串主键。
    5. Native:本地策略,可以在Identity和Sequence之间进行自动切换。
    6. Assignedhibernate放弃外键管理,需要通过手动编写程序或者自己设置。
    7. Foreign:外部的,一对一的关联映射的情况下使用。(了解)

     

     

    3持久化类的三种状态

    3.1持久化类的三种状态

    Hibernate是持久层框架,通过持久化类完成ORM操作,为了更好的管理持久化类,hIbernate把持久化类分层三种转态。

    持久化类=Java类+映射

     

    (1)瞬时态(Transient):没有唯一标识OID,没有被Session管理。

     

    2)持久态(Persistent):有唯一标识OID,被Session管理。

    (持久化类的持久态对象,可以自动更新数据库)

     

    (3)脱管态(Detached):有唯一标识OID,没有被Session管理。

     

    3.2区分三种状态对象

     

    @Test
    
         // 三种状态区分
    
         public void demo1() {
    
    
    
             // 1通过工具类获取Session
    
             Session session = HibernateUtils.openSession();
    
             // 2开启事务
    
             Transaction tx = session.beginTransaction();
    
             // 3操作
    
             // 向数据库插入一条记录
    
             Customer Customer = new Customer(); // 1.瞬时态:没有位移标识OID(主键id),没有被session管理
    
        
    
             Customer.setCust_name("小涵涵"); //             
    
                                             
    
             session.save(Customer); // 2.持久太:有唯一标识OID,被session管理
    
             // 4事务提交 //                                  
    
             tx.commit(); //                               
    
             // 5释放资源 //                                  
    
             session.close(); //                            
    
                                    
    
             System.out.println(Customer.getCust_name()); // 3.托管态:有唯一标识OID,没有被session管理
    
         }

     

    3.3持久化类的状态转换(了解)

     

    1. 瞬时态:

    获得:由new关键字创建

    1. 瞬时态转换为持久态:执行Session中的save()方法或saveOrUpdate0方法
    2. 瞬时态转换为脱管态:为瞬时态对象设置持久化标识OID
      Customer customer = new Customer)://瞬时态customersetCust id(1); //脱管态

    (2)持久态,
    获得,通过Session的get()、load()方法或者Quey查询从数据库中获得.

    1. 持久态转换为瞬时态:执行Session中的delete()方法。
    2. 持久态转换为脱管态:执行Session的evict()、close()或clear()方法用于清除一级缓存中某个对象,clear()清除一级缓存 中的所有对象。

    (3)脱管态,
    获得,脱管态无法获得,只能由其他状态转换而来。

    1. 脱管态转换为持久态, 执行Session的update()、 saveOrUpdate()或lock()方法。
    2. 脱管态转换为瞬时态,将脱管态对象的持久化标识OID设置为null

    3.4持久化类持久态对象自动更新数据库

    @Test
    
        /****
    
         * 持久太的对象可以以自动更新数据库
    
         */
    
        public void demo2() {
    
    
    
            // 1通过工具类获取Session
    
            Session session = HibernateUtils.openSession();
    
            // 2开启事务
    
            Transaction tx = session.beginTransaction();
    
            // 3操作
    
            /** 获取一个持久太对象了 **/
    
            Customer Customer = (Customer) session.get(Customer.class, 1l);
    
            Customer.setCust_name("王哈哈");
    
            /** 此处可以省略一个update(如果此处数据和数据库一样,不执行Update()) **/
    
            //session.update(Customer);
    
            // 4事务提交
    
            tx.commit();
    
            // 5释放资源
    
            session.close();
    
        }
    
    
    
    
    
    

    4Hibernate的一级缓存

    4.1缓存概述

    缓存是一种优化的方式,将一些数据放在内存,使用的时候直接从缓存中获取,不用通过数据源。

    4.2Hibernate缓存

    4.2.1Hibernate一级缓存

    Hibernate一级缓存又称为“Session的缓存

    Session内置不能被卸载,Session的缓存是事务范围的缓存(Session对象的生命周期通常对应一个数据库事务或者一个应用事务)。

    一级缓存中,持久化类的每个实例都具有唯一的OID

    依赖于hibernate一级缓存【就是将数据库/硬盘文件中数据,放到缓存中(就是内存中一块空间),当再次使用时,可以直接从内存中获取数据信息】。

    4.2.2证明Hibernate一级缓存存在

    @Test
    
        /****
    
         * 证明一级缓存的存在
    
         */
    
        public void demo3() {
    
    
    
            // 1通过工具类获取Session
    
            Session session = HibernateUtils.openSession();
    
            // 2开启事务
    
            Transaction tx = session.beginTransaction();
    
            // 3操作
    
           
    
            /**
    
             * 分别用两次get执行两次查询id=1的客户,按道理执行两次get应发送两条sql语句,
    
             * 且Customer1与Customer2不是同一个对象,
    
             * 实际上只发送一次,且Customer1与Customer2是同一个对象
    
             * 证明第二次查询使用的是一级缓存中的数据
    
             **/
    
            /** 数据库中第一本书的信息 **/
    
            Customer Customer1 = (Customer) session.get(Customer.class, 1l);
    
            System.out.println(Customer1);
    
            /** 一级缓存中中第一本书的信息 **/
    
            Customer Customer2 = (Customer) session.get(Customer.class, 1l);
    
            System.out.println(Customer2);
    
           
    
            System.out.println(Customer1==Customer2);
    
            // 4事务提交
    
            tx.commit();
    
            // 5释放资源
    
            session.close();
    
        }
    
    
    
    

     

    4.2.3Hibernate一级缓存结构

     


     

    @Test
    
        /****
    
         * 深入了解持久态的对象可以以自动更新数据库
    
         * 基于一级缓存:快照区
    
         */
    
        public void demo4() {
    
    
    
           // 1通过工具类获取Session
    
           Session session = HibernateUtils.openSession();
    
           // 2开启事务
    
           Transaction tx = session.beginTransaction();
    
           // 3操作
    
           Customer Customer = (Customer) session.get(Customer.class, 1l);
    
           /** 将信息存储于快照区 **/
    
           Customer.setCust_name("张三丰");// 先将一级缓存区的【cust_name】修改为【"张三丰"】-----中间会进行一个比对查看是否一致,如果一致不更新(不会执行update语句),如果不一致----再将快照区中的【cust_name】修改为【"张三丰"】(执行update语句)。
    
           // 4事务提交
    
           tx.commit();
    
           // 5释放资源
    
           session.close();
    
        }
    
    

    5Hibernate的事务管理

    5.1什么是事务

     

    事务:指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。

    5.2事务的特性

    1.原子性

    (Atomic)(Atomicity)

    事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。

    2.一致性

    (Consistent)(Consistency)

    事务在完成时,必须使所有的数据都保持一致状态。

    3.隔离性

    (Insulation)(Isolation)

    由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。

    4.持久性

    (Duration)(Durability)

    事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

    5.3如果不考虑隔离性,引发安全性问题

    读的问题:

    脏读:一个事务读到另一个事务未提交的数据。

    不可重复读:一个事务读到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致。

    虚读:一个事务读到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致。

     

    写问题(了解)

         引发丢失更新。

    5.3读问题的解决

    设置事务的隔离级别

       Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

       Repeatable read (可重复读):可避免脏读、不可重复读的发生。

       Read committed (读已提交):可避免脏读的发生。

       Read uncommitted (读未提交):最低级别,任何情况都无法保证。

    MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

    5.4Hibernate设置事务隔离级别

    核心配置文件中加入:

    <!--  事务隔离级别
    
                0:TRANSACTION_NONE
    
                1:TRANSACTION_READ_UNCOMMITTED
    
                2:TRANSACTION_READ_COMMITTED
    
                4:TRANSACTION_REPEATABLE_READ
    
                8:TRANSACTION_SERIALIZABLE
    
    -->
    
    <property name="hibernate.connection.isolation">4</property>

       

     

    5.5Hibernate解决Service的事务管理

    改写工具类:

    package top.yangxianyang.utils;
    
    
    
    import org.hibernate.Session;
    
    import org.hibernate.SessionFactory;
    
    import org.hibernate.cfg.Configuration;
    
    
    
    /**
    
     * Hibernate的工具类
    
     * @author yxy
    
     *
    
     */
    
    public class HibernateUtils {
    
    
    
        public static final Configuration cfg;
    
        public static final SessionFactory sf;
    
       
    
        static{
    
           cfg = new Configuration().configure();
    
           sf = cfg.buildSessionFactory();
    
        }
    
        /*
    
         * 提供获得session的方法
    
         */
    
        public static Session openSession(){
    
           return sf.openSession();
    
        }
    
       
    
        /*
    
         * 提供获得session的方法
    
         */
    
        public static Session getCurrentSession(){
    
           return sf.getCurrentSession();
    
        }
    
    }
    
    

    核心文件配置:

    <!-- 配置当前线程绑定的Session -->
    
           <property name="hibernate.current_session_context_class">thread</property>

          

    代码:

    package top.yangxianyang.demo1;
    
    
    
    import org.hibernate.Session;
    
    import org.hibernate.Transaction;
    
    import org.junit.Test;
    
    
    
    import top.yangxianyang.utils.HibernateUtils;
    
    
    
    
    
    /*
    
     * Hibernate线程绑定Session
    
     * @author yxy
    
     *
    
     */
    
    public class HibernateTest3 {
    
    
    
       
    
        @Test
    
        public void demo1(){
    
           Session session=HibernateUtils.getCurrentSession();
    
           Transaction tx=session.beginTransaction();
    
          
    
           Customer Customer = new Customer();
    
           Customer.setCust_name("涵涵"); 
    
          
    
           session.save(Customer);
    
          
    
           tx.commit();
    
          
    
        }
    
    }
    
    
    
    
    
    

     

    6Hibernate的其他API

    6.1Query

    1 使用query对象,不需要写sql语句,但是写hql语句

    (1)hql:hibernate query language,hibernate提供查询语言,这个hql语句和普通sql语句很相似

    (2)hql和sql语句区别:

    - 使用sql操作表和表字段

    - 使用hql操作实体类和属性

     

    2 查询所有hql语句:

    (1)from 实体类名称

     

    3 Query对象使用

    (1)创建Query对象

    (2)调用query对象里面的方法得到结果


     

    @Test
    
        //Query
    
        public void demo1(){
    
            Session session=HibernateUtils.getCurrentSession();
    
            Transaction tx=session.beginTransaction();
    
            //通过session获得Query接口
    
            //String hql="from Customer";//简单查询
    
            //条件查询
    
            //String hql="from Customer where cust_name like ?";
    
            //分页查询
    
            String hql="from Customer";
    
           
    
            Query query=session.createQuery(hql);
    
            //设置条件
    
            //query.setParameter(0, "张%");
    
            //设置分页
    
            query.setFirstResult(0);
    
            query.setMaxResults(2);
    
            List<Customer> list=query.list();
    
           
    
            for (Customer customer : list) {
    
                System.out.println(customer);
    
            }
    
           
    
            tx.commit();
    
           
    
        }
    
    
    
    
    
    

    6.2Criteria

    1使用这个对象时候,不需要写语句,直接调用方法实现,更加面向对象。

    2 实现过程

    (1)创建criteria对象

    (2)调用对象里面的方法得到结果 

       @Test
    
        //Criteria
    
        public void demo2(){
    
           Session session=HibernateUtils.getCurrentSession();
    
           Transaction tx=session.beginTransaction();
    
           //通过session获得Criteria对象
    
           Criteria ct=session.createCriteria(Customer.class);
    
           //条件查询
    
           ct.add(Restrictions.like("cust_name", "张%"));
    
           List<Customer> list=ct.list();
    
           //分页
    
           ct.setFirstResult(0);
    
           ct.setMaxResults(2);
    
          
    
          
    
          
    
           for (Customer customer : list) {
    
               System.out.println(customer);
    
           }
    
          
    
           tx.commit();
    
          
    
        }
    
    

     

    6.3SQLQuery

     

    1 使用hibernate时候,调用底层sql实现

    2 实现过程

    (1)创建对象

    (2)调用对象的方法得到结果


     

    @Test
    
        // 查询所有
    
        public void demo6(){
    
            Session session = HibernateUtils.openSession();
    
            Transaction tx = session.beginTransaction();
    
           
    
            // 接收SQL:
    
            SQLQuery query = session.createSQLQuery("select * from cst_customer");
    
            List<Object[]> list = query.list();
    
            for (Object[] objects : list) {
    
                System.out.println(Arrays.toString(objects));
    
            }
    
            tx.commit();
    
            session.close();
    
        }
    
    
    
    
    
    
    
    

     

    今天任务完成。

    源码地址:

    链接:https://pan.baidu.com/s/1rMQ9XBMIeu2O_VbNZBo3MQ 密码:0hgz

     

     

  • 相关阅读:
    14:求满足条件的3位数
    1696:逆波兰表达式
    筛法求素数 6分
    1751:分解因数
    1750:全排列
    1788:Pell数列
    666:放苹果
    06:寻宝
    04:最匹配的矩阵
    雷电
  • 原文地址:https://www.cnblogs.com/yangxianyang/p/13675675.html
Copyright © 2020-2023  润新知