百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

ORM框架Hibernate基础探秘(orm框架的原理是什么)

mhr18 2024-10-09 12:22 37 浏览 0 评论

《“爱读书”--给你讲技术》,我来看书,你来进步,让我们开始吧!

本书简介

书名为《轻量级JavaEE企业应用实战》,是本人在学习JavaEE框架的时候阅读的第一本书,本书对于框架及相关基础知识讲述的比较详细和浅显,适合初学者和需要全面了解JavaEE知识的人群。

本文内容为本书第五章

ORM和Hibernate

1.对象关系数据库映射

ORM的全称是Object/Relation Mapping,对象/关系数据库映射。ORM实现了面向对象的编程语言到关系数据库的映射,它既可利用面向对象语言的简单易用性,又可利用关系数据库的技术优势。ORM作用是把对持久化对象的保存、删除、修改等操作,转换成对数据库的操作。

JPA规范就是一种ORM规范,JPA规范并不提供任何ORM实现,只提供了系列面向的编程接口

2.基本映射方式

ORM有如下几条映射关系:

  • 数据表映射类:持久化类被映射到一个数据表。当时用持久化类来创建实例、修改属性、删除实例时,系统将自动转换成对这个表的CRUD操作。
  • 数据表的行映射对象(即实例):持久化类会生成很多实例,每个实例就对应数据表中的一行记录。
  • 数据表的列映射对象的属性:当修改某个持久化对象的指定属性时,ORM将转换成对数据表中指定数据行和数据列的操作。

Hibernate实现数据库操作

PO(持久化对象),作用是完成持久化操作,可通过该对象进行增删改查操作。Hibernate直接采用了POJO作为PO,不要求继承任何父类或实现任何接口。仅仅JavaBean并不具备持久化操作能力,需要结合映射文件。所以说PO=POJO+映射文件

除此之外,数据库的基本配置需要通过Hibernate配置文件来实现。默认的配置文件为hibernate.cfg.xml。

为了使用Hibernate进行持久化操作,通常步骤如下:

(1)开发持久化类,由POJO加映射文件组成

(2)获取SessionFactory

(3)获取Session,打开事务

(4)用面向对象的方式操作数据库

(5)关闭事务,关闭Session

PO的三种状态

  • 瞬态:如果PO实例从未与Session关联,则PO处于瞬态
  • 持久化:如果PO实例与Session关联起来,且该实例对应到数据库记录,则处于持久化态
  • 托管:如果PO实例曾与Session关联过,但因为Session关闭等原因,PO实例脱离了Session的管理,则处于托管状态

对PO的操作必须在Session管理下才能同步到数据库。Session由SessionFactory工厂产生,SessionFactory是数据库编译后的内存镜像,通过一个应用对应一个SessionFactory。SessionFactory由Configuration对象产生,Configuration对象负责加载Hibernate配置文件

Hibernate体系结构

PS:由上图可见Hibernate体系结构是有PO+映射文件实现了应用对数据库的操作

Hibernate 持久化解决方案如下图:

PS:Hibernate持久化解决方案将用户从原始的JDBC访问中释放出来,用户无需关注底层的JDBC操作,而是以面向对象的方式进行持久层操作。底层数据连接的获取、数据访问的实现、事务控制都无需用户关心。

下面我们逐一解释图中的一些关键词

  • SessionFactory:这是Hibernate关键对象,它是单个数据库映射关系经过编译后的内存镜像,它是线程安全的,是生成Session的工厂。
  • Session:它是应用与持久化层之间交互操作的一个单线程对象,也是Hibernate持久化操作的关键对象,所有持久化对象必须在Session的管理下才可以进行。它底层封装了JDBC连接,是Transaction工厂。Session对象持有一个必选的以一级缓存,显示执行flush前,所有数据都缓存在Session中。
  • 持久化对象:系统创建的POJO实例,一旦与Session关联,并对应数据表的指定记录,该对象处于持久化状态。在程序中对持久化对象执行的修改,都将自动被转换为持久层的修改。
  • 事务(Transaction):代表一个原子操作,它具有数据库事务的概念。Hibernate事务是对底层具体的JDBC、JTA的抽象。在某些情况下,一个Session可能包含多个Transaction对象,所有的持久化操作都应该在事务管理下进行,即使是只读操作。
  • 连接提供者(ConnectionProvider):它是生成JDBC连接的工厂。它通过抽象将应用于底层的DataSource或DriverManager隔离开。实际应用中ConnnectProvider通常由DataSource充当,由于SessionFactory底层封装了ConnnectProvider,因此SessionFactory底层封装了DataSource。
  • 事务工厂(TransactionFactory):它是生成Transaction实例的工厂。该对象无须应用直接访问,它负责对底层具体的事务实现进行封装,将底层具体的事务抽象成Hibernate事务。

深入Hibernate配置文件

1.创建Configuration对象

每个Hibernate配置文件对应一个Configuration对象。Configuration实例的唯一作用是创建SessionFactory实例,一旦SessionFactory创建完成,它就被丢弃了。

可通过如下几种方式配置Hibernate,他们创建Configuration实例的方式不同:

  • 使用hibernate.properties文件
  • 使用hibernate.cfg.xml文件
  • 以编码方式创建Configuration
  • 2.配置的JDBC连接属性

    3.数据库方言

    Hibernate底层依然使用SQL语句来执行数据库操作,但不同关系型数据库的SQL都略有不同,所以我们需要告诉Hibernate底层使用了哪种数据库,这就是数据库方言。设置了方言后,Hibernate将自动应付底层数据库访问所存在的差异。

    4.二级缓存相关属性

    5.其他常用配置属性

    • hibernate.show_sql:是否在控制台输出Hibernate生成的SQL语句,只能是true或false
    • hibernate.format_sql:是否将SQL语句转成格式良好的SQL,只能使true或false
    • hibernate.use_sql_comments:是否在Hibernate生成SQL语句中添加注释,true或false
    • hibernate.jdbc.fetch_size:指定JDBC抓取数据数量的大小
    • hibernate.jdbc.batch_size:指定JDBC批量更新的大小
    • hiberante.connection.autocommit:设置是否自动提交,不建议打开
    • hibernate.hbm2ddl.auto:设置创建SessionFactory时,是否根据映射文件自动建立数据库表。如使用create-drop,则关闭SessionFactory时将drop刚建的数据表。该属性可以为update、create、create-drop。

    深入Hibernate映射文件

    1.映射文件结构

    映射文件的根元素为<hibernate-mapping>,该元素下可以拥有多个<class>子元素,每个<class>子元素对应一个持久化类的映射。

    <hibernate-mapping>
        <class/>
        <class/>
    </hibernate-mapping>

    <hibernate-mapping>元素属性:

    • schema:指定所映射数据库的schema名,如果制定了该属性,则表名会自动添加schema前缀
    • catalog:指定所映射数据库的catalog名,如果指定了该属性,则表名会自动添加catalog前缀
    • default-cascade:设置默认级联风格,默认值none。当配置java属性映射和集合映射时还可指定cascade属性,用于覆盖默认值。
    • default-access:指定默认的属性访问策略,默认值property,即使用getter和setter方法来访问属性。如果指定access="field",则会忽略getter和setter方法,而通过反射来访问成员变量。
    • default-lazy:设置默认延迟加载策略,默认值true,即启动延迟加载策略。当配置java属性映射和集合映射时还可指定lazy属性,用于覆盖默认值。
    • auto-import:设置是否允许在查询语言中使用非全限定类名。默认值true。
    • package:指定一个包前缀,用于映射文件中没有指定全限定类名,则默认使用该包前缀

    <class>元素属性:

    • name:指定该持久化类的全限定类名
    • table:指定该持久化类的表名,默认已持久化类的类名作为表名
    • dynamic-update:指定用于更新记录的update语句是否在运行时动态生成,并且只更新那么些改变过的字段。默认false。
    • dynamic-insert:指定用于插入记录的insert语句是否在运行时动态生成,并且只插入那些非空字段。默认false。
    • select-before-update:指定在更新某个持久化对象之前是否需要先进行一次查询。如果为true,则可以保证只有当持久化对象的状态被修改过时,才会使用update语句来保存其状态。默认false。
    • where:指定一个附加的SQL语句中过滤条件。
    • batch-size:指定来抓取实例时每批抓取的实例数。默认1
    • optimistic-lock:指定乐观锁策略。默认值version

    2.映射主键

    Hibernate需要给每个持久化类定义一个标识属性,用于唯一的标识某个持久化实例,该标识属性需要映射到数据库的主键。

    标识属性通过<id>元素指定,元素的属性如下:

    • name:指定持久化类标识属性名。
    • type:指定该标识属性的数据类型。既可以是Hibernate内建类型,也可以是java类型,java类型需使用全限定类名。
    • column:设置标识属性所映射的数据列的列名
    • access:指定访问标书属性的访问策略

    主键生成器使用<generator>元素,class属性为生成器策略:

    • increment:为long、short、int类型主键生成唯一标识。多进程下不要使用。
    • indentity:在DB2、MySQL、SQL Server等提供自增主键的数据库中使用。
    • sequence:在Oracle等提供序列支持的数据库中使用。
    • uuid:用128位的UUID算法生成字符串类型的标识符。
    • native:根据底层数据库的能力选择indentity、sequence或hilo中的一个
    • assigned:让应用在save()之前为对象手工设置一个标识符
    • foreign:表明直接使用另一个关联的对象的标识属性值

    举例如下:

    3.映射普通属性

    使用<property>元素来映射普通属性。元素属性如下:

    • name:映射持久化类的属性名
    • column:配置该属性所对应的数据表的列名
    • type:指定普通属性的数据类型
    • update、insert:用于设置生成的update或insert语句中是否需要包含该字段,默认true
    • formula:指定一个SQL表达式,指定该属性的值将根据表达式来计算
    • access:指定访问该属性的访问策略,默认是property
    • lazy:指定当该实例属性第一个被访问时,是否启动延迟加载。默认false
    • unique:设置是否为该属性所映射的数据列添加唯一约束
    • not-null:设置是否为该属性所映射的数据列添加not null约束
    • optimistic-lock:设置该属性在进行更新时是否需要使用乐观锁。默认true,即属性值发生改变时,版本号增加
    • generated:设置该属性映射的数据列的值是否由数据库生成。包括never、insert、always
    • length:指定该属性所映射的数据列的字段长度
    • precision:指定该属性所映射数据列的有效数字位数
    • scale:指定该属性所映射数据列的小数位数

    4.映射集合属性

    两个持久化对象不能共享一个集合元素的引用

    集合映射元素包括:

    • list:用于映射List集合属性
    • set:用于映射Set集合属性
    • map:用于映射Map集合属性
    • array:用于映射数组集合属性

    映射集合属性的元素包含如下属性:

    • name:该集合属性的名称
    • table:指定保存集合属性的表名
    • schema:指定集合属性的数据表schema名称
    • lazy:设置是否启动延迟加载,默认true
    • inverse:指定该集合关联的实体在双向关联中不控制关联关系
    • cascade:指定对持久化对象的操作是否会级联到它所关联的子实体
    • order-by:用于设置数据库对集合元素排序
    • sort:指定集合的排序顺序
    • where:指定任意的SQL语句中where条件
    • batch-size:定义延迟加载时每批抓取集合元素的数量,默认1
    • access:指定访问集合属性的访问策略,默认property

    因为集合属性都需要保存到另一个数据表中,所以保存集合属性的数据表必须包含一个外键列,通过在<set>、<list>元素中使用<key>子元素来映射,key属性如下:

    • column:指定外键字段的列名
    • on-delete:指定外键约束是否打开数据库级别的级联删除
    • property-ref:指定外键引用的字段是否为原表的主键

    映射集合元素的索引列:

    • <list-index>:用于映射List集合、数组的索引列
    • <map-key>:用于映射Map集合、基本数据类型的索引列

    映射集合的集合元素:

    • <element>:集合元素是基本类型、字符串和日期是使用
    • <composite-element>:集合元素是复合类型时使用
    • <one-to-many>或<many-to-many>:集合元素是其他持久化对象的引用时使用

    (1)List集合属性

    (2)数组属性

    (3)Set集合属性

    (4)Map集合属性

    5.映射组件属性

    组件属性意思是持久化类的属性的类型是复合类型的对象,它仅被当做值类型,并非引用另一个持久化实体。

    我们使用<component>元素来映射组件属性

    • name:指定该组件属性的名称
    • class:指定组件类的类名
    • lazy:设置该组件是否在持久化对象第一次被访问时启动延迟加载。默认值true
    • optimistic-lock:设置更新该组件属性是否需要获取乐观锁

    一个自定义类通常包括其他属性,通过为<component>元素增加<property>子元素来实现。

    例如:

    使用JPA Annotation标注实体

    用注解来定义一个实体类

    @Entity用于标注该类是一个持久化类

    @EmbeddedId用于标注符合类型的标识属性

    @Embedded用于标注一个组件属性

    配置了上面的注解,也就不再需求*.hbm映射文件了,接下来我们需要配置hibernate.cfg.xml让Hibernate去加载指定实体类,而不是根据映射文件加载。配置如下图:

    相关推荐

    Java培训机构,你选对了吗?(java培训机构官网)

    如今IT行业发展迅速,不仅是大学生,甚至有些在职的员工都想学习java开发,需求量的扩大,薪资必定增长,这也是更多人选择java开发的主要原因。不过对于没有基础的学员来说,java技术不是一两天就能...

    产品经理MacBook软件清单-20个实用软件

    三年前开始使用MacBookPro,从此再也不想用Windows电脑了,作为生产工具,MacBook可以说是非常胜任。作为产品经理,值得拥有一台MacBook。MacBook是工作平台,要发挥更大作...

    RAD Studio(Delphi) 本月隆重推出新的版本12.3

    #在头条记录我的2025#自2024年9月,推出Delphi12.2版本后,本月隆重推出新的版本12.3,RADStudio12.3,包含了Delphi12.3和C++builder12.3最...

    图解Java垃圾回收机制,写得非常好

    什么是自动垃圾回收?自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用...

    Centos7 初始化硬盘分区、挂载(针对2T以上)添加磁盘到卷

    1、通过命令fdisk-l查看硬盘信息:#fdisk-l,发现硬盘为/dev/sdb大小4T。2、如果此硬盘以前有过分区,则先对磁盘格式化。命令:mkfs.文件系统格式-f/dev/sdb...

    半虚拟化如何提高服务器性能(虚拟化 半虚拟化)

    半虚拟化是一种重新编译客户机操作系统(OS)将其安装在虚拟机(VM)上的一种虚拟化类型,并在主机操作系统(OS)运行的管理程序上运行。与传统的完全虚拟化相比,半虚拟化可以减少开销,并提高系统性能。虚...

    HashMap底层实现原理以及线程安全实现

    HashMap底层实现原理数据结构:HashMap的底层实现原理主要依赖于数组+链表+红黑树的结构。1、数组:HashMap最底层是一个数组,称为table,它存放着键值对。2、链...

    long和double类型操作的非原子性探究

    前言“深入java虚拟机”中提到,int等不大于32位的基本类型的操作都是原子操作,但是某些jvm对long和double类型的操作并不是原子操作,这样就会造成错误数据的出现。其实这里的某些jvm是指...

    数据库DELETE 语句,还保存原有的磁盘空间

    MySQL和Oracle的DELETE语句与数据存储MySQL的DELETE操作当你在MySQL中执行DELETE语句时:逻辑删除:数据从表中标记为删除,不再可见于查询结果物理...

    线程池—ThreadPoolExecutor详解(线程池实战)

    一、ThreadPoolExecutor简介在juc-executors框架概述的章节中,我们已经简要介绍过ThreadPoolExecutor了,通过Executors工厂,用户可以创建自己需要的执...

    navicat如何使用orcale(详细步骤)

    前言:看过我昨天文章的同鞋都知道最近接手另一个国企项目,数据库用的是orcale。实话实说,也有快三年没用过orcale数据库了。这期间问题不断,因为orcale日渐消沉,网上资料也是真真假假,难辨虚...

    你的程序是不是慢吞吞?GraalVM来帮你飞起来性能提升秘籍大公开

    各位IT圈内外的朋友们,大家好!我是你们的老朋友,头条上的IT技术博主。不知道你们有没有这样的经历:打开一个软件,半天没反应;点开一个网站,图片刷不出来;或者玩个游戏,卡顿得想砸电脑?是不是特别上火?...

    大数据正当时,理解这几个术语很重要

    目前,大数据的流行程度远超于我们的想象,无论是在云计算、物联网还是在人工智能领域都离不开大数据的支撑。那么大数据领域里有哪些基本概念或技术术语呢?今天我们就来聊聊那些避不开的大数据技术术语,梳理并...

    秒懂列式数据库和行式数据库(列式数据库的特点)

    行式数据库(Row-Based)数据按行存储,常见的行式数据库有Mysql,DB2,Oracle,Sql-server等;列数据库(Column-Based)数据存储方式按列存储,常见的列数据库有Hb...

    AMD发布ROCm 6.4更新:带来了多项底层改进,但仍不支持RDNA 4

    AMD宣布,对ROCm软件栈进行了更新,推出了新的迭代版本ROCm6.4。这一新版本里,AMD带来了多项底层改进,包括更新改进了ROCm的用户空间库和AMDKFD内核驱动程序之间的兼容性,使其更容易...

    取消回复欢迎 发表评论: