Hibernate 學習筆記

来源:https://www.cnblogs.com/xiqingbo/archive/2022/03/22/java-24.html
-Advertisement-
Play Games

Hibernate 是一個開放源代碼的對象關係映射框架,它對 JDBC 進行了非常輕量級的對象封裝,它將 POJO 與資料庫表建立映射關係,是一個全自動的 orm 框架 ...


hibernate(持久化)

一. Hibernate 的理解

Hibernate 是数据访问层(Dao层),就是把数据存入到数据库中,称为持久化。

Hibernate 对 JDBC 进行了封装,针对数据访问层提出面向对象的思想,操作对象间接的操作数据库中的表,自动生成 SQL 语句,可以简化数据访问层的代码,提高开发效率。

二. hibernate的优缺点

  • 优点:

    • 使用 JDBC 遇到的问题:

      1. 代码中存在大量的 SQL 语句

      2. 查询结果需要手动封装到 Model

      3. SQL 语句中存储大量的?,需要手动赋值

      4. SQL 语句根据不同的数据库,有不同的函数,如果更换数据库,需要大量更改 SQL 语句,针对数据库移植性差

    • 使用 Hibernate 可以解决以上问题:

      1. Hibernate 操作对象自动生成 SQL 语句

      2. 查询结果自动赋值给 Model 类

      3. 自动赋值

      4. Hibernate 使用的是 HQL 语句,根据不同的方言,生成不同数据库的 SQL 语句,到达跨数据库平台

        注:数据迁移是软性项目中的大事情,特别难做,做项目时对数据库的选型尤为重要

  • 缺点:

    1. SQL语句自动生成,人工无法控制,使得 SQL 语句执行效率慢
    2. Hibernate 执行效率低
    3. Hibernate 特别耗内存,有一系列缓存机制

三. 什么是ORM(☆)

ORM 是一种编程思想(开发模式),全称:Object Relation Mapper(对象关系映射)

是为了解决面向对象与面向关系型数据库不匹配现象,通过一个配置文件把面向对象与面向关系型数据库关联起来

  • 类 --- 表
  • 属性 --- 字段
  • 对象 --- 记录
优点:使得数据访问层更面向对象,不用考虑关系型数据库,只要会面向对象即可,开发程序变简单了(Hibernate、MyBatis、Spring、JDBC)

四、搭建 Hibernate 环境

  1. 导包:在hibernate-release-4.3.11.Final/lib/required下所有 Jar 文件与数据库驱动包复制到项目中
  2. 引入 Hibernate 主配置文件,Hibernate.cfg.xml文件复制到项目中的 src 目录
  3. 创建一个 Model 类实现 Serializable 接口,对应一个表,并且在映射文件xxx.hbm.xml中配置
  4. 编写 Hibernate API 进行测试

五. Hibernate 的体系结构(Hibernate由哪几部分组成)(☆)

结构 描述
hibernate.cfg.xml 是 Hibernate 的主配置文件,用来配置数据库连接信息与 Hibernate 相关参数
XXX.hbm.xml 类与表之间的映射文件,一个类对应一个表,一个属性对应一个字段
实体类 用于封装数据库的表,一定要实现 Serializable 接口
Hibernate API 用于读取并解析配置文件,然后根据映射关系生成 SQL 语句,间接操作数据库

六. Hibernate 工作原理(☆)

  1. Configuration 类读取并解析配置文件(主配置文件、映射文件)
  2. 创建 SessionFactory(一个 SessionFactory 对应一个数据库)
  3. 打开 Session(Session 代表程序与数据库之间的一次会话,用来做表的增删改查)
  4. 创建事务(Transaction 代表数据库事务)
  5. 持久化操作(增删改查)
  6. 提交事务
  7. 关闭 Session
  8. 当应用程序停止,关闭 SessionFactory

注:SessionFactory 是一个重量级对象,创建销毁特别耗资源,应用程序创建一次,关闭一次

七. Hibernate 代码工作原理

  1. 获取 Configuration 类的对象(cfg)

  2. 调用 cfg.configure() 方法默认读取 src 根目录下的 hibernate.cfg.xml

  3. 调用cfg.buildSessionFactory()方法创建 Session 工厂(sf)

  4. 调用sf.openSession()方法获取 Session

  5. 若为添加、删除、修改操作,则开启事务

    Transaction ts = session.getTransaction()
    ts.begin();
    
  6. 进行持久化操作

    添加:e(obj);			
    删除:delete(obj);			
    修改:update(obj);			
    查询:get(类名.class, 1);	
    查询:load(类名.class, 1);
    添加和修改都支持:saveOrUpdate(obj);	
    
  7. 提交事务,关闭 Session,关闭 SessionFactory

    ts.commit();
    session.close();
    sf.close();
    

八. Hibernate 的映射类型

Hibernate 映射文件xxx.hbm.xml中,Java 数据类型与数据库数据类型相互转换,通过 type 属性进行指定,类型如下:
  1. 整数

    Java 类型 type 取值
    byte byte
    short short
    int Integer
    long long
  2. 小数

    Java 类型 type 取值
    float float
    double double
  3. 字符串

    Java 类型 type 取值
    String String
  4. 日期

    Java 类型 type 取值
    java.util.Date date
    java.sql.Date date
  5. 时间

    Java 类型 type 取值
    java.sql.Timestamp timestamp

注:建议手动创建表,不要让 Hibernate 生成表格,hibernate.hbm2ddl.auto配置成为 update

九. Hibernate 核心开发接口(常用的类与接口)(☆)

接口 描述
Configuration 读取并解析配置文件,然后创建 SessionFactory(是一个类)
SessionFactory 代表一个数据库,一个 SessionFactory 对应一个数据库,用于创建 Session(是一个接口)
Session 程序与数据库的一次会话,用于数据库表的增删改查(是一个接口)
Transaction 事务管理(是一个接口)
Query 与 Criteria 用于数据查询(是一个接口)

十. Hibernate 有多少种查询

  1. 主键查询:get()load()
  2. HQL 查询
  3. SQL 查询
  4. QBC 查询

查询效率由高到低排列:主键查询 > SQL 查询 > HQL 查询 > QBC 查询

十一. 查询方法延迟加载(☆)

  1. 什么是延迟加载?

    Hibernate 中存在一些方法,在查询的时候并没有马上发送 SQL 语句去数据库查询,而是返回一个空值对象,空值对象不是 null,而是新 new 出来的对象,除主键以外其他属性值为空,当程序真正使用到此对象时,才会发送 SQL 语句去数据库中查询,并且将结果赋值给此对象,这种查询称为延迟加载

  2. 为什么要用延迟加载?

    1. 在延迟的这段时间内,并没有访问数据库,可以节约内存开销,减少数据库的访问,提高使用效率
    2. 可以防止查询对象,但并没有真正的使用,这种情况下可以节约内存,减少数据库访问
  3. 如何使用延迟加载?

    1. Hibernate 中一些方法自带延迟加载机制,只要调用这些方法,就可以使用延迟加载

    2. 具有延迟加载机制的访问如下

      延迟加载 立即加载
      session.load() session.get()
      query.iterate() query.list()
  4. get() 与 load() 区别(☆)

    get():立即加载,立即发送 SQL 语句查询,如果没有查询到结果返回 null

    load():延迟加载,不会立即发送 SQL 语句查询,返回一个空值对象,真正使用到此对象,才会发送 SQL 语句。如果没有查询到结果,会抛出ObjectNotFoundException异常

  5. list() 与 iterate() 区别

    list():立即加载,立即发送 SQL 语句查询,返回一个对象集合,如果没有查询到数据,返回空集合

    iterate():延迟加载,首先会发送一条 SQL 语句把表中所有主键查询出来,在遍历的时候,根据主键发送 SQL 语句单个查询,有多少条记录就会发送多少条 SQL 语句查询

    注:建议使用立即加载

十二. 一级缓存(☆)

  1. 什么是一级缓存?

    Hibernate 在创建 Session 的时候,会给每个 Session 另外分配一片内存空间,用于缓存 Session 操作过的对象,这块儿内存称为一级缓存,一级缓存是

    Session 管理并且使用的,所以也称为:Session 缓存。

    一级缓存的生命周期与 Session 一致,Session 被创建时,一级缓存空间被分配,session.close()时,一级缓存被回收

  2. 一级缓存的作用?

    一级缓存用来缓存 Session 操作过的对象,相同数据不用每次都去查询数据库,直接从一级缓存中获取,提高查询效率

  3. 一级缓存的步骤?

    Session 优先查询一级缓存,首先去一级缓存中查询,查询不到才会发送 SQL 语句查询数据库,查询到结果之后会在一级缓存中存放一份,再次查询时,无需发送 SQL 语句查询数据库,直接从一级缓存中获取(在 Hibernate 中一级缓存优先于数据库,一级缓存与数据库数据不同步时,以一级缓存为主)

  4. 如何使用一级缓存?

    1. 一级缓存是默认开启,自动使用

    2. 一级缓存的特征:

      • 一级缓存是 Session 独享的,Session 与 Session 之间不能共享数据
      • Session 查询一组数据时,会将一组数据拆开存入一级缓存中,一级缓存中存储的是单个对象
      • 执行增删改时会同步一级缓存,当delete(Object obj)时,在一级缓存中会标记此对象可能被删除,再次查询时不会发送 SQL 语句查询,返回一个null 对象
    3. 管理缓存

      • clear():清空一级缓存
      • evict():清空一级缓存单个对象
      • flush():手动同步一级缓存与数据库,数据不一样,以一级缓存为主

十三. 二级缓存

SessionFactory 级别的缓存(需要配置)

Hibernate 二级缓存需要配置,在同一 SessionFactory 范围内,查询同一个对象多次,只会发送一条 SQL 语句(只会去数据库中查询一次),后面每次查询都是从二级缓存中去取数据

配置信息:
  1. 导入二级缓存的 Jar 包 ehcache oscache
  2. 把对应配置文件放入到 src 根目录下
  3. Hibernate.cfg.xml中开启二级缓存
  4. 声明哪些对象需要放入到二级缓存中

十四. 对象的持久性

什么是对象的持久性?

​ Hibernate 操作对象时,可以把对象看成三种状态::瞬时态,持久台,游离态/托管态

三种状态的规则?
  1. 瞬时态(transient)

    • 定义:对象刚刚被 new 出来,称为瞬时态
    • 规则:瞬时态可以被垃圾回收机制回收,一级缓存中没有,数据库中没有
  2. 持久态(persistent)

    • 定义:一级缓存中有,数据库中有,称为持久态
    • 规则:通过 save(),update(),saveOrUpdate(),get(),load(),HQL,SQL,QBC 方式操作过的对象,称为持久态对象
  3. 游离态(detached)

    • 定义:一级缓存中没有,数据库中有,称为游离态
    • 规则:通过 clear,evict,close 方式操作过的对象, 称为游离态对象

十五. 主键的生成策略

在映射文件(xxx.hbm.xml)中需要配置主键字段,并且需要配置主键的生成策略,通过 generator 标签指定
主键生成策略:
  1. sequence

    代码如下:

    <generator class="sequence">
    	<!-- 指定序列的名称 -->
    	<param name="sequence">t_person_seq</param>
    </generator>
    

    对应数据库:Oracle,DB2

  2. identity

    代码如下:

    <generator class="identity"></generator>

    对应数据库:MySQL,SQL Server

  3. native

    代码如下:
    <generator class="native"></generator>

    含义:native 是让 hibernate 自动选择一种主键方式,根据配置文件中的方言,从 sequence 与 identity 中选一个,方言配置的是 Oracle ,自动选择sequence,方言配置的是MySQL,自动选择 identity

  4. assigned

    代码如下:

    <generator class="assigned"></generator>

    含义:程序员手动分配主键,Hibernate 不会自动生成

  5. uuid

    代码如下:

    <generator class="uuid"></generator>

    含义:采用 UUID 算法生成一个32位十六进制的字符串作为主键

  6. increment

    代码如下:

    <generator class="increment"></generator>

    含义:查询表中最大 id 值, 把最大 id + 1 生成主键

    优点:适用与任何数据库

    缺点:并发量大时,会产生相同的 id,线程不安全,不推荐使用

十六. 关系映射

什么是关系映射?

​ 如果两张表之间有关系,Hibernate 允许我们将关系提取出来,并且映射的配置文件中,在对一个表的增删改查操作,Hibernate 通过这个映射关系,间接的操作另一张表的增删改查,这两个表的关系配置称为关系映射

关系映射类型?
  1. 多对一
  2. 一对多
  3. 一对一
  4. 多对多

十七. 多对一(重点)与一对多

  1. 设计

    两张表之间的关系为多对一或一对多,会在多的一端增加一个字段指向一的那端的主键

  2. 案例

    学生与班级:多个学生属于一个班级,一个班级有多个学生

    一对多添加会产生 N+1 条,尽量少用一对多,用多对一代替

    一对多配置:
    <!--
    set标签:指定是 set 集合
    name属性:类中的属性名
    -->
    <set name="students">
    
    <!--
    key标签:指定两个表之间关联字段(外键字段名称)
    column属性:外键字段的字段名
    -->
    <key column="f_classId"></key>
    
    <!--
    one-to-many标签:表示与哪个类发生了一对多的关系
    class属性:多对那端类的名称
    -->
    <one-to-many class="Student" />
    </set>
    
    多对一配置:
    <!--
    many-to-one 标签:多对一关系
    name 属性:类中属性的名称
    column 属性:表中的字段名(外键字段名)
    class 属性:外键属性的类(完整路径)
    -->
    <many-to-one name="cla" column="f_classId" class="com.zt.model.Classes"></many-to-one>
    

十八. 关联操作

关联查询(查询)
  • 延迟加载(对于关联属性,Hibernate 默认采用的是延迟加载,查询一端数据,不会关联出另一端数据)

    lazy="proxy/true" 	默认方式,采用懒加载
    lazy="false"		立即加载,关联的表数据会同时查询出来
    
  • 连接查询

    fetch="select"	默认方式,使用多条 SQL 语句查询
    fetch="join"	使用连接查询,一条 SQL 语句完成查询,使用此属性懒加载失效
    
  • join 查询

    String hql = "from Student s left join fetch s.cla";  左外连接
    String hql = "from Student s inner join fetch s.cla";  内连接
    
级联操作(增删改)
  • 什么是级联操作?

    在对一张表做增删改操作时,关联的另一张表也做增删改操作,称为级联操作

  • 如何设置级联操作?

    在映射文件中,关联映射配置 cascade 属性,用这个属性定义级联操作

  • cascade取值如下:

取值方式 描述
none 默认方式,不支持级联
all 支持增删改
save-update 支持增,改
delete 支持删

十九. 一对一(了解)

一对一的类型:

​ 主键一对一:包装两个标段主键相同

​ 外键一对一:在任意一端增加一个字段(外键字段)指向另一端的主键,并且这个字段有唯一约束(不能重复)

案例:

​ 学生与档案一对一,在学生表中增加一个字段指向档案表的主键,外键保证唯一性

二十. 多对多

什么是多对多?

​ 如果两张表的关系是多对多,必然产生一张中间表,中间表只有两个字段,分别为两张表的外键字段,这两个外键字段组合成复合主键

案例:

​ 一个班级由多个老师教学,一个老师可以教多个班级

多对多配置:
<!-- 
set标签:指定是 set 集合
name属性:类中的属性名
table:中间表的表名
-->
<set name="teachers" table="t_cla_tea">

<!--
column属性:当前表的主键的对应中间表的外键字段
-->
<key column="f_classId"></key>

<!--
many-to-many标签:多对多的关系映射
class属性:当前 set 集合元素对应的类名
column属性:对方表的主键对应中间表的外键字段名
-->
<many-to-many class="Teacher" column="f_teacherId"/>
</set>

二十一. Hibernate 查询语句

  1. 主键查询:load,get
  2. HQL 查询(Hibernate Query Language) :标准的SQL + 面向对象语言
  3. QBC 查询(Query By Criteria):完全的面向对象
  4. SQL 查询(Structured Query Language):结构化查询语言

本文来自博客园,作者:Schieber,转载请注明原文链接:https://www.cnblogs.com/xiqingbo/p/java-24.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 開源項目其實有一個成熟周期,這個周期大概是三年左右,自React框架在2013年發佈並引爆了前端框架的大潮,這個屬於前端的周期就此開始了。之後在2015年5月開源的React Native又開啟了屬於Web移動前端的周期,15-16年,18-19年,21-22年正好就是屬於移動前端的三個爆發點。 ...
  • 描述: 本篇文章為了記錄日常生活中或者項目中經常使用到的JS方法,會長期記錄... 數組中的方法 1.map和forEach方法 map 參數為回調函數,得到一個新數組 forEach 修改原數組,不會產生新數組 2.pop和push方法(棧結構) push 向數組末尾添加一個元素或者多個元素,會改 ...
  • 前言 在 《一篇帶你用 VuePress + Github Pages 搭建博客》中,我們使用 VuePress 搭建了一個博客,最終的效果查看:TypeScript 中文文檔。 本篇講講 SEO 中的一些細節優化。 1. 設置全局的 title、description、keywords // co ...
  • word-break: normal; // 此值為瀏覽器的預設屬性:以單詞為單位; keep-all 這個值由於相容性差,很少用;word-wrap: normal; // 此值為瀏覽器的預設屬性:以單詞為單位; 純中文:自動換行,一個漢字看做一個單詞; 純英文或純數字:看做一個單詞,不換行; 遇 ...
  • 經過前面兩天的學習,已經對Node.js有了一個初步的認識,今天繼續學習其他內容,並加以整理分享,如有不足之處,還請指正。 ...
  • 外觀模式是什麼 外觀模式是一種結構性設計模式,它能為程式庫、框架或者其他複雜的子系統提供一個統一的高層界面,使子系統更容易使用。外觀模式就是聚合多個介面實現,對外只暴露單個介面。隱藏子系統的複雜性。調用方不關心實現步驟。 為什麼要用外觀模式 當子系統提供的功能很多,而我們子需要多個子系統中很少的幾個 ...
  • 1. Consul 簡介 Consul是 HashiCorp 公司推出的開源工具,用於實現分散式系統的服務發現與配置。與其它分散式服 務註冊與發現的方案,Consul 的方案更“一站式”,內置了服務註冊與發現框 架、分佈一致性協議實 現、健康檢查、Key/Value 存儲、多數據中心方案,不再需要依 ...
  • 1.依賴配置 1.1 pom文件 <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <flink.version>1.13.0< ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...