Hibernate3入门之第二章一级缓存和持久化类

2024-03-05 08:58

本文主要是介绍Hibernate3入门之第二章一级缓存和持久化类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Hibernate3入门之第二章一级缓存和持久化类

上节课程回顾

  1. Hibernate快速入门:

    • 下载Hibernate开发包.

    • Hibernate开发包目录结构:

      • 文档:

      • 开发包:

        • 操作字节码:

        • 必须的

        • 可选的

        • jpa

      • 项目:

    • 创建一个java项目导入相应jar包.

    • 创建数据库表:

    • 创建一个实体类:

    • 建立映射:

    • 创建Hibernate核心配置文件:

    • 编写一个测试类:

  2. Hibenrate的CRUD的操作:

    • save(); / update(); / delete(); / get()/load();

    • get()/load()的区别

      get :采用是立即检索,马上发送SQL查询.返回的是真实对象.检索一个找不到的对象的时候NullPointException

      load :采用延迟加载技术,当真正使用这个对象的时候,才会发送SQL.返回代理对象.检索一个找不到的对象的时候ObjectNotFoundException

  3. Hibernate的常见配置及API:

    • 核心配置:两种方式;

      • 属性文件的方式:

        在src下创建一个hibernate.properties.。手动加载映射文件.

      • XML格式的配置:

        在src下创建一个hibernate.cfg.xml

      • 必须的配置:

        数据库连接信息.。 Hibernate的方言.

      • 可选配置

        显示SQL。格式化SQL。hbm2ddl.auto(create/create-drop/update/validate)

    • 映射配置:

      • <class>建立类与表映射

        name :类的全路径.。table :表名称

      • <id>

        name。column。type。length

      • <property>

        name。column。type。length

  4. Hibernate的API

    • Configuration:管理配置信息.

      属性文件---->直接创建.

      XML---------->new Configuration().configure();

    • SessionFactory:

      维护二级缓存,线程安全的对象

    • Session

      维护一级缓存,线程不安全的对象

    • Transaction

      事务是默认不自动提交,手动提交事务.

    • Query

    • Criteria

  5. 持久化类编写:

    • 持久化类:就是一个实体类 + XML映射.

    • 编写原则:

          无参数构造:属性提供set/get方法提供为一个标识:尽量使用包装类型:这个类尽量不要使用final修饰.
      
    • 自然主键和代理主键:

    • Hibernate提供主键生成策略:

       increment	:自动增长.适合 short int long...不是使用数据库的自动增长机制.使用Hibernate框架提供的自动增长方式.select max(id) from 表; 在最大值的基础上+1.(多线程的问题.)在集群下不要使用identity		:自动增长.适合 short int long采用数据库的自动增长机制.不适合于Oracle数据库.sequence	:序列.适用于 short int long ... 应用在Oracle上 .uuid		:适用于字符串类型的主键.采用随机的字符串作为主键.native		:本地策略.底层数据库不同.自动选择适用identity 还是 sequence.assigned		:Hibernate框架不维护主键,主键由程序自动生成.foreign		:主键的外来的.(应用在多表一对一的关系.)

Hibernate的持久化类状态

  • 持久化类状态

持久化类:就是一个实体类 与 数据库表建立了映射.

Hibernate为了方便管理持久化类,将持久化类分成了三种状态.

状态特点
Transient瞬时态:持久化对象没有唯一标识OID.没有纳入Session的管理
Detached脱管态:持久化对象有唯一标识OID,没有纳入到Session管理
Persistent持久态:持久化对象有唯一标识OID.已经纳入到Session的管理.

同时对于持久态而言:持久化持久态对象有自动更新数据库的能力

  • 区分三种持久化对象的状态:

使用代码进行说明

	// 关于瞬时态、持久态和托管态的理解public void test1() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = new Book(); // 瞬时态 没有唯一标识OID 没有与session关联book.setName("Mybitas开发");book.setAuthor("孙XX");book.setPrice(60d);session.save(book);// 持久态 有唯一标识OID 与session关联ts.commit();book.setName("SpringMVC开发");// 托管态 有唯一标识OID 没有与session关联}
  • 三种状态对象转换:

    • 瞬时态:

      获得:
      Book book = new Book();瞬时--->持久save(book);save()/saveOrUpdate();
      瞬时--->脱管book.setId(1);
    • 脱管态:

      获得:
      Book book = new Book();
      book.setId(1);脱管--->持久:
      * session.update();
      * update()/saveOrUpdate()/lock()脱管--->瞬时:
      * book.setId(null);
      
    • 持久态:

      获得:
      Book book = (Book)session.get(Book.class,1);get()/load()/find()/iterate();持久--->瞬时:delete(book);特殊状态:删除态.(被删除的对象,不建议去使用.)持久--->脱管:session.close();close()/clear()/evict();
      
  • 持久态对象有自动更新数据库的能力;

    // 持久态有自动更新数据库的能力public void test2() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = (Book) session.get(Book.class, 1);book.setName("SpringMVC开发");// 提交事务时进行更新// session.update(book);//持久态 自动更新数据库不需要更新操作ts.commit();// 利用hibernate的一级缓存,提交事务之后发送sql语句直接更新}
    

Hibernate的一级缓存

  • 什么是缓存:

    缓存将数据库/硬盘上文件中数据,放入到缓存中(就是内存中一块空间).当再次使用的使用,可以直接从内存中获取.

  • 缓存的好处:

    提升程序运行的效率.缓存技术是Hibernate的一个优化的手段.

  • Hibernate分成两个基本的缓存:

    一级缓存:Session级别的缓存.一级缓存与session的生命周期一致.自带的.不可卸载.

    二级缓存:SessionFactory级别的缓存.不是自带的.

在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期.

  • 证明Hibernate的一级缓存的存在:

    	// 证明一级缓存的存在public void test3() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = new Book();book.setName("SpringBoot开发");book.setAuthor("乔峰");book.setPrice(46d);// 保存之后会将保存图书的id返回Integer id = (Integer) session.save(book);//// 再次取得图书,看书否会发送sql语句Book book1 = (Book) session.get(Book.class, id);//// 当获取图书的时候是不会去发送sql语句的System.out.println(book1);ts.commit();}
    

    当执行session.save(book);之后,程序执行插入(insert)并将数据保存在一级缓存中,所以在session.get(Book.class, id);时不再发送任何SQL语句,直接从一级缓存中获取

  • 深入理解一级缓存中快照区:

	// 证明一级缓存的快照区public void test4() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book1 = (Book) session.get(Book.class, 1);book1.setName("Hibernate3开发");ts.commit();}

断点调试:在Book book1 = (Book) session.get(Book.class, 1);处设置断点;在Variables窗口处找到

session—>h—>realSession—>persistenceContext–>entityEntries

在entityEntries集合(Map)中存放着一级缓存区(key)和快照区(value)

快照举例说明:

在你很久没有回家以后,当你回到家中你周围的邻居对你有一个印象(快照),当你再次回到家中的时候,你得邻居会,将现在看到你的模样和他们现在看到你的模样进行对比,是否发生了变化。

在这里插入图片描述

结论:向一级缓存存入数据的时候,放入一级缓存区和一级缓存快照区,当更新了一级缓存的数据的时候,事务一旦提交,比对一级缓存和快照区,如果数据一致,不更新,如果数据不一致,自动更新数据库.

  • Hibernate管理一级缓存:

    一级缓存是与session的生命周期相关的.session生命周期结束,一级缓存销毁了.

    方法描述
    clear()清空一级缓存中所有的对象.
    evict(Object obj)清空一级缓存中某个对象.
    flush()刷出缓存.
    refresh(Object obj)将快照区的数据重新覆盖了一级缓存的数据.

    举例说明:

    ​ clear()清空缓存区所有数据
    ​ evict(指定对象)清空缓存区指定对象的数据

    	
    public void test5() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book1 = (Book) session.get(Book.class, 1);Book book2 = (Book) session.get(Book.class, 2);System.out.println(book1);System.out.println(book2);// 上面的发送sql语句,下面的不再发送// session.clear();session.evict(book1);Book book4 = (Book) session.get(Book.class, 2);Book book3 = (Book) session.get(Book.class, 1);System.out.println(book1);System.out.println(book2);ts.commit();}
    

    ​ flush()指明发送SQL语句的时机
    ​ refresh()在更新之前快照区将一级缓存区数据覆盖

    public void test6() {Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book1 = (Book) session.get(Book.class, 1);book1.setName("PHP开发");// session.flush();// 只是发送sql语句而不执行更新// ts.commit();// 执行更新session.refresh(book1);ts.commit();}
    
  • Hibernate一级缓存的刷出时机

    FlushMode:常量:* ALWAYS		:每次查询的时候都会刷出.手动调用flush.事务提交的时候.* AUTO			:默认值.有些查询会刷出.手动调用flush.事务提交的时候.* COMMIT		:在事务提交的时候,手动调用flush的时候.* MANUAL		:只有在手动调用flush才会刷出.严格程度:MANUAL > COMMIT > AUTO > ALWAYS

操作持久化对象的方法


hibernate update 只更新部分字段的3种方法

  • 在进行测试时忽然想到,关系update 的一些问题,Hibernate 中如果直接使用Session.update(Object o);或者session.saveOrUpdate(Object o);(由托管态转为持久态时),在使用这两者的时候,会把这个表中的所有字段更新一遍。且没有设置的将置为默认值(null)。

            Session session = Hibernate3Utils.openSession();Transaction ts = session.beginTransaction();Book book = new Book();// 托管态book.setId(8);book.setAuthor("孙XX");ts.commit();
    

    发送的更新语句:

    Hibernate: updateBOOK setNAME=?,AUTHOR=?,PRICE=? whereID=?
    

    我们可以通过先查询后修改的方式进行只修改部分字段的值

            Book book = (Book) session.get(Book.class, 8);book.setName("深度学习");session.saveOrUpdate(book);//session.update(book);
    
  • 同时因为上面的原因,会把所有字段遍历一遍,这样效率会很低。

    那么怎么只更改我们更新的字段呢?同时提升效率呢

    有三种方式:

    • 第一种方式:

      1.XML中设置property 标签 update = “false” ,如下:我们设置 age 这个属性在更改中不做更改

       	<property name="price" type="java.lang.Double" update="false" ><column name="PRICE" /></property>等价<property name="price" update="false"></property>
      

      2.同时在Annotation(注解)中,在属性GET方法上加上@Column(updatable=false)

      	@Column(updatable = false)public Double getPrice() {return price;}
      

      3.缺点就是不灵活。。。

    • 第二种方法

      1.使用XML中的 dynamic-update=“true”

        <class name="com.syj.vo.Book" table="BOOK"  dynamic-update="true">......</class>
      

      2.这样就不需要在字段上设置了。

      3.但这样的方法在Annotation中没有

    • 第三种方式

      1.使用HQL语句(灵活,方便)

      public void update(){Session session =  HibernateUitl.getSessionFactory().getCurrentSession();session.beginTransaction();Query query = session.createQuery("update Book b set b.name = 'Python' where id = 8");query.executeUpdate();session.getTransaction().commit();}
      

      2.Hibernate 执行的SQL语句:

      Hibernate: updateBOOK setNAME='Python' whereID=8
      

      3.这样就只更新了我们更新的字段

这篇关于Hibernate3入门之第二章一级缓存和持久化类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/775956

相关文章

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

SpringCloud之consul服务注册与发现、配置管理、配置持久化方式

《SpringCloud之consul服务注册与发现、配置管理、配置持久化方式》:本文主要介绍SpringCloud之consul服务注册与发现、配置管理、配置持久化方式,具有很好的参考价值,希望... 目录前言一、consul是什么?二、安装运行consul三、使用1、服务发现2、配置管理四、数据持久化总

Linux修改pip和conda缓存路径的几种方法

《Linux修改pip和conda缓存路径的几种方法》在Python生态中,pip和conda是两种常见的软件包管理工具,它们在安装、更新和卸载软件包时都会使用缓存来提高效率,适当地修改它们的缓存路径... 目录一、pip 和 conda 的缓存机制1. pip 的缓存机制默认缓存路径2. conda 的缓

Redis解决缓存击穿问题的两种方法

《Redis解决缓存击穿问题的两种方法》缓存击穿问题也叫热点Key问题,就是⼀个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击,本文给大家介绍了Re... 目录引言解决办法互斥锁(强一致,性能差)逻辑过期(高可用,性能优)设计逻辑过期时间引言缓存击穿:给

Python FastAPI入门安装使用

《PythonFastAPI入门安装使用》FastAPI是一个现代、快速的PythonWeb框架,用于构建API,它基于Python3.6+的类型提示特性,使得代码更加简洁且易于绶护,这篇文章主要介... 目录第一节:FastAPI入门一、FastAPI框架介绍什么是ASGI服务(WSGI)二、FastAP

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

一文详解Nginx的强缓存和协商缓存

《一文详解Nginx的强缓存和协商缓存》这篇文章主要为大家详细介绍了Nginx中强缓存和协商缓存的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、强缓存(Strong Cache)1. 定义2. 响应头3. Nginx 配置示例4. 行为5. 适用场景二、协商缓存(协

Golang基于内存的键值存储缓存库go-cache

《Golang基于内存的键值存储缓存库go-cache》go-cache是一个内存中的key:valuestore/cache库,适用于单机应用程序,本文主要介绍了Golang基于内存的键值存储缓存库... 目录文档安装方法示例1示例2使用注意点优点缺点go-cache 和 Redis 缓存对比1)功能特性

MySQL8.0设置redo缓存大小的实现

《MySQL8.0设置redo缓存大小的实现》本文主要在MySQL8.0.30及之后版本中使用innodb_redo_log_capacity参数在线更改redo缓存文件大小,下面就来介绍一下,具有一... mysql 8.0.30及之后版本可以使用innodb_redo_log_capacity参数来更改

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查