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

相关文章

java如何实现高并发场景下三级缓存的数据一致性

《java如何实现高并发场景下三级缓存的数据一致性》这篇文章主要为大家详细介绍了java如何实现高并发场景下三级缓存的数据一致性,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 下面代码是一个使用Java和Redisson实现的三级缓存服务,主要功能包括:1.缓存结构:本地缓存:使

Apache Ignite缓存基本操作实例详解

《ApacheIgnite缓存基本操作实例详解》文章介绍了ApacheIgnite中IgniteCache的基本操作,涵盖缓存获取、动态创建、销毁、原子及条件更新、异步执行,强调线程池注意事项,避免... 目录一、获取缓存实例(Getting an Instance of a Cache)示例代码:二、动态

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

从入门到进阶讲解Python自动化Playwright实战指南

《从入门到进阶讲解Python自动化Playwright实战指南》Playwright是针对Python语言的纯自动化工具,它可以通过单个API自动执行Chromium,Firefox和WebKit... 目录Playwright 简介核心优势安装步骤观点与案例结合Playwright 核心功能从零开始学习

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Redis的持久化之RDB和AOF机制详解

《Redis的持久化之RDB和AOF机制详解》:本文主要介绍Redis的持久化之RDB和AOF机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述RDB(Redis Database)核心原理触发方式手动触发自动触发AOF(Append-Only File)核