hibernate sqlserver 对象名无效_ORM框架Hibernate基础探秘

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

本书简介

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

本文内容为本书第五章

f202e137008cb72b45db1661cae03406.png

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体系结构

c0dd945a3c8ad4eb20f359a48ff0f7d5.png

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

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

1c6ce7cec84a1ba4fc4902d5c5edb2f0.png

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文件
4fdf5c4de89d32026676d2a6b8030866.png
使用hibernate.cfg.xml文件
9915a5292ed20b532b1365dccfc260be.png
以编码方式创建Configuration
e747ca91c0d0c653395c4edf53dcaa76.png

2.配置的JDBC连接属性

1aba2a976159c4d6d362096e03203533.png

3.数据库方言

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

412eaccb3f75edf095d3201f58fa62c0.png
730921c72855acd7d8c567e654c97f94.png

4.二级缓存相关属性

b02bcdbb379ba2d77f332735365331af.png

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.映射文件结构

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

元素属性:

  • 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:指定一个包前缀,用于映射文件中没有指定全限定类名,则默认使用该包前缀

元素属性:

  • 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需要给每个持久化类定义一个标识属性,用于唯一的标识某个持久化实例,该标识属性需要映射到数据库的主键。

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

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

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

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

举例如下:

637c77d7c7a64468190713a0af45cff2.png

3.映射普通属性

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

  • 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

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

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

映射集合元素的索引列:

  • :用于映射List集合、数组的索引列
  • :用于映射Map集合、基本数据类型的索引列

映射集合的集合元素:

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

(1)List集合属性

34e43641041a32b8162c51912b602773.png

(2)数组属性

ef0f359913de8712633c54ceeabf3477.png

(3)Set集合属性

a68451afae2950772507d59f1fae5d33.png

(4)Map集合属性

6c20728b86a46d6e74ebf2a9ecbcac2f.png

5.映射组件属性

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

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

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

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

例如:

3cce6dea6e4909258614b9d96bb569b2.png
2c9d4c0e94a371379f4df348e9b2bfc9.png

使用JPA Annotation标注实体

用注解来定义一个实体类

317ab79870b03d5ba658269b747f2d0c.png
ac243218141ee61de167f32583ceb35e.png

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

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

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

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

39d8b472ff7ecf07090811cd2b3a1435.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值