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

相关文章

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

Java实现本地缓存的常用方案介绍

《Java实现本地缓存的常用方案介绍》本地缓存的代表技术主要有HashMap,GuavaCache,Caffeine和Encahche,这篇文章主要来和大家聊聊java利用这些技术分别实现本地缓存的方... 目录本地缓存实现方式HashMapConcurrentHashMapGuava CacheCaffe

如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)

《如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)》:本文主要介绍如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)问题,具有很好的参考价值,希望对大家有所帮助,如有... 目录先在你打算存放的地方建四个文件夹更改这四个路径就可以修改默认虚拟内存分页js文件的位置接下来从高级-

PyCharm如何更改缓存位置

《PyCharm如何更改缓存位置》:本文主要介绍PyCharm如何更改缓存位置的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录PyCharm更改缓存位置1.打开PyCharm的安装编程目录2.将config、sjsystem、plugins和log的路径

JSR-107缓存规范介绍

《JSR-107缓存规范介绍》JSR是JavaSpecificationRequests的缩写,意思是Java规范提案,下面给大家介绍JSR-107缓存规范的相关知识,感兴趣的朋友一起看看吧... 目录1.什么是jsR-1072.应用调用缓存图示3.JSR-107规范使用4.Spring 缓存机制缓存是每一

Spring 缓存在项目中的使用详解

《Spring缓存在项目中的使用详解》Spring缓存机制,Cache接口为缓存的组件规范定义,包扩缓存的各种操作(添加缓存、删除缓存、修改缓存等),本文给大家介绍Spring缓存在项目中的使用... 目录1.Spring 缓存机制介绍2.Spring 缓存用到的概念Ⅰ.两个接口Ⅱ.三个注解(方法层次)Ⅲ.

Spring Boot 整合 Redis 实现数据缓存案例详解

《SpringBoot整合Redis实现数据缓存案例详解》Springboot缓存,默认使用的是ConcurrentMap的方式来实现的,然而我们在项目中并不会这么使用,本文介绍SpringB... 目录1.添加 Maven 依赖2.配置Redis属性3.创建 redisCacheManager4.使用Sp

springboot项目redis缓存异常实战案例详解(提供解决方案)

《springboot项目redis缓存异常实战案例详解(提供解决方案)》redis基本上是高并发场景上会用到的一个高性能的key-value数据库,属于nosql类型,一般用作于缓存,一般是结合数据... 目录缓存异常实践案例缓存穿透问题缓存击穿问题(其中也解决了穿透问题)完整代码缓存异常实践案例Red

Redis持久化机制之RDB与AOF的使用

《Redis持久化机制之RDB与AOF的使用》:本文主要介绍Redis持久化机制之RDB与AOF的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis持久化机制-RDB与AOF一、RDB持久化机制1、RDB简介2、RDB的工作原理3、RDB的优缺点4

POI从入门到实战轻松完成EasyExcel使用及Excel导入导出功能

《POI从入门到实战轻松完成EasyExcel使用及Excel导入导出功能》ApachePOI是一个流行的Java库,用于处理MicrosoftOffice格式文件,提供丰富API来创建、读取和修改O... 目录前言:Apache POIEasyPoiEasyExcel一、EasyExcel1.1、核心特性