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虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

使用Spring Cache本地缓存示例代码

《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac... 目录一、Spring Cache简介核心特点:二、基础配置1. 添加依赖2. 启用缓存3. 缓存配置方案方案

Java实现本地缓存的四种方法实现与对比

《Java实现本地缓存的四种方法实现与对比》本地缓存的优点就是速度非常快,没有网络消耗,本地缓存比如caffine,guavacache这些都是比较常用的,下面我们来看看这四种缓存的具体实现吧... 目录1、HashMap2、Guava Cache3、Caffeine4、Encache本地缓存比如 caff

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

史上最全MybatisPlus从入门到精通

《史上最全MybatisPlus从入门到精通》MyBatis-Plus是MyBatis增强工具,简化开发并提升效率,支持自动映射表名/字段与实体类,提供条件构造器、多种查询方式(等值/范围/模糊/分页... 目录1.简介2.基础篇2.1.通用mapper接口操作2.2.通用service接口操作3.进阶篇3

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Python实现Word转PDF全攻略(从入门到实战)

《Python实现Word转PDF全攻略(从入门到实战)》在数字化办公场景中,Word文档的跨平台兼容性始终是个难题,而PDF格式凭借所见即所得的特性,已成为文档分发和归档的标准格式,下面小编就来和大... 目录一、为什么需要python处理Word转PDF?二、主流转换方案对比三、五套实战方案详解方案1:

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用