Hibernate框架简介
Hibernate框架是一款数据持久型的框架也是一款ORM框架
数据持久型:是将数据存入数据库或将数据库里的数据读入程序中
ORM:我们说JAVA中是面向对象的思想 而现在市场中大部分使用的数据库都是关系型数据库,如果利用面向对象语言来操作关系型数据库的话,其中会出现一些很麻烦的代码,会阻碍我们进行开发造成了没必要的麻烦,所以ORM提供了一种能使用对象来调用数据库里的每一条数据,具体是以类来对应数据库中的表,以对象来对应表中的字段,以对象来对应表中的每一条数据。
在了解Hibernate之前 首先回顾一下JDBC是如何操作数据库的
1,加载mysql驱动
2,获取连接
3,获取数据的操作对象
4,进行数据库的操作
5,关闭资源
在Hibernate结构目录中分别有以下几个结构
documentation(文档)
lib(jar包)
project(源代码)
对于初学这款框架的程序员来说 先进入lib包下进行导包
hibernate框架的jar包就分的很详细
lib中会发现有这几种envers jpa optional osgi required
一般情况下只导入required下的jar包即可 这些jar都是必须存在的
optional中的jar包主要是用于优化hibernate的性能 包括数据连接池和缓存两部分
接下来了解下Hibernate的相关配置
hibernate的配置分为两种
首先hibernate配置文件(hibernate.cfg.xml)配置的全是通用的属性,主要用于配置数据库连接以及hibernate的一些通用的属性。
再来就是映射文件的配置(xxx.hbm.xml),这个配置文件只对某个类起作用,用来配置class类到数据表的一个映射.
类的属性到数据表里字段的映射,对象到数据表里每一条记录的映射.
hibernate配置文件
主要是用来配置数据连接以及hibernate属性:方言 自动建表 显示sql语句等等;
重点了解下自动建表这个属性设置
hibernate.hbm2ddl.auto
有以下这几种属性: create update create-drop validate
create:在每次 创建sessionFactory时都会创建一个表,在有这张表的情况下,会将这将表删除并重新创建一次。
update:增量更新数据库,如果说所对应的实体类有更改的话,会用这个属性增加数据库里的数据,会将相应字段增加到原来的表中,而且字段只会越来越多 不会减少。
create-drop:这个属性是用来创建临时表的,首先跟create一样在每次创建sessionFactory时都会创建一个表,而如果调用了sessionFactory中的close方法 即就将该数据表删除了。
validate:校验的属性,实体类中配置的属性,数据表中必须与之对应,不然测试中就会出现报错。
hibernate映射文件
主要是用来配置 类到表 属性到字段 对象到每一条记录 的映射.
以下配置
package:对应的是实体类的包,
理论上是可以在一个映射文件中写多个类的,实际上我们只用写一个映射文件来对应一个类即可.
class标签:class标签对应的就是实体类
属性主要有
name:对应java实体类的类名,这个是必须要有的
table:对应的是数据库中的表名,这个可选,如果不写的话所对应的表名直接就默认是java实体类的名字了
(数据库中是不区分大小写的)
class子元素
id:对应的就是数据库中的主键,即java实体类中id的主键(hibernate中必须要求提供主键)
property:对应的是普通的属性,即数据库中的某一列字段.
(最后将映射文件的路径配置到hibernate配置文件中的mapping属性即可)
--------------------------------
以上都是初识hibernate进行的相关配置与了解,可以说是运用hibernate的一些准备工作,在学习每一款框架时我们都要了解其中的核心思想,从而才能运用的如鱼得水一般,学习一款框架之前 也要尝试的去爱上他 这样才能深刻的了解对方 最主要的就是能拿到手好好对待他。
Hibernate中的三种状态
前面都说到hibernate是基于ORM的框架,是通过对象来操作关系型数据库的。
从而为了保证操作数据稳定的进行,hibernate把对象定义了三种状态
即 瞬态,持久态,游离态。
瞬态:也称临时状态,在每一次创建新的对象的时候出现的状态。
存在于JVM内存中,这时hibernate根本就不知道他的存在,在等待hibernate将他转化为持久态。
持久态:(在hibernate中调用session工厂,然后再调用openSession获得hibernate中的session对象)这个session对象在调用save或者update等方法时 就直接将瞬态的对象转化为持久态的对象。
此时对象由JVM虚拟机内存中转化到session的缓存当中,此时该对象等待与数据库进行同步操作。
游离态:通过事务提交,将数据存入到数据库中。
此时如果session关闭,此时的对象就转化成了游离态。
三种状态之间的转化不光是从瞬态到持久态再到游离态,也可以从游离态到持久态再到瞬态,总之三者是缺一不可的,必须是逐渐一步到一步的转化,绝对不可跨级转化!
从游离态到持久态的转化是session的get或load方法通过对象将数据库中的正处于游离态的一条数据直接转化成持久态。
也可以这样理解,相当于就是我们平常从数据库中通过某个ID值获得的一条数据。
如果还想将这个持久态的对象转化成瞬态对象,直接调用delete方法删除即可。
Hibernate的主键生成策略
关于hibernate的主键生成,上面说到hibernate中是必须提供主键的。
每个实体类对应的数据表必须要有个主键列,每个主键列的赋值就是hibernate的主键生成策略。
在这里我按自己的理解将主键分为 数字型类和字符串型类已经其他的通用型类。
类型中有很多赋值的方法,在这里只指明一些比较常见的
数字型类的赋值策略:
首先数字型类在数据库中一般对应的都是int类型,在java中对应的类型有int ,long,short,byte(后几个不太常用)
increment:自增的。适用于Mysql,SQL server等数据库中,以数字做主键,基于查询的。
缺点是:线程不安全,容易产生并发问题。
所以一般不会考虑id会重复的情况下来使用,id几乎都是连续的。
identity:自增的。使用于Mysql,SQL server等数据库中,以数字做主键。
基于数据库底层实现的,所以线程较为安全。
sequence:序列。适用于Oracle,DB2等数据库,以数字做主键。
字符串类型的主键赋值策略:
一般都会使用uuid这个类型,uuid是现在比较经典的表示id的一种模式,据说全球中每个uuid都是唯一的。
uuid与uuid2 两种相似
其他通用类型的赋值策略:
native :主键不用管,全靠数据库。
assigned:主键框架不用管,有程序处理。
foreign:使用某个表的主键做本表的外键。
Hibernate的关联操作
顾名思义 mysql里就触及到多表联查的功能,Hibernate当然也不例外,提供了如何对多张表进行联查的简单的配置。
多张表的联查分别有 一对多 | 多对一 | 多对多 | 一对一 的这几种状态
这里首先要理解这几个状态,举个平时都见过的例子,(淘宝购物系统)
在淘宝上每次购物都要下订单,订单当然可以下多个,所有在一个用户中对应多个订单,这时候的关联状态就是一对多。
在订单的角度去看 是多个订单都对应一个用户,所以这时候的关联状态则是多对一。
在订单中都会有多个商品,而在商品中也会有多个订单同时都购买他,所以这时候的状态就是多对多。
最后一对一的这种关联状态 在生活中也很少见,以后用的也相对少一点,比如一个人只对应一个身份证,身份证也只对应这一个人,这时候才能构建出一对一的关联状态。
关联也分两种性质
双向关联:在有关联关系的两个对象中都将关系体现了出来,在查询的时候 两边都可以查到对方的信息。
维护关系的时候 两边都可以维护。
单向关联:在有关联关系的其中一个对象中将关系体现出来,在查询的时候 只有这一边可以查到对方的信息。
维护关系的时候 只有这一边要进行维护。
项目大部分的时候 我们使用的都是单向关联,因为双向关联容易造成死循环,维护起来也麻烦
下面来具体介绍下这几种关联状态的关系
单向关联一对多
首先创建两张表所都对应的实体类,提供get set方法 这里必须要有空参的构造方法,如果要设置有参的构造,另外要再写一个空参的构造。
在实体类 要多写一个用来配置关系的属性,这里一对多的情况下 要用set集合存放多的那一实体类中的数据,所以要通过set集合的类型来添加这个属性,比如 private Set<所对应多的实体类的类> 也要同时设置get set方法.
下一步就是在配置关系的这个类的映射文件中 配置Set的标签 以及 one to money 的标签属性
<set name="Set属性中的名字" cascade="一般定义 save或者 save-update 属性 要想通过一张表进行全删的话 配置all属性">
<key column="这里对应的是关系表的外键 一般显示到多的那一方数据表中"></key>
<one-to-many class="对应集合里面的元素类型">
</set>
这样配置文件大体上就完工了,下来再看如何将一张表中的数据 存放到另一张表的对应关系中。
首先通过 session.get()方法将 数据库中的记录 转化为 持久态的状态。
在一的一方要调用set集合的对象
再通过Set集合里的add方法 将一方的数据存进这张关系表中。提交事务从而达成两张表的连接关系.
单向关联多对一
多对一跟一对多相比 实现的关联效果是一样的,就是从不同角度来建立关系,之前一对多是根据Set集合来存储多的数据,在多对一的角度来看, 不需要利用集合,因为所需要关联的对象仅此只有一个,所以在实体类中 只需要 配置 所对应关系的实体类的 类和类名 即可。
在配置映射文件中也非常的简单,
只需要配置 many to one 这个标签里的属性即可
<many to one name="" class="" column=""></many to one>
name是对应实体类中配置的 对应一的属性名 class是对应一的类名 column 一样表示的是外键列.
多对一的实际操作也非常简单,直接通过实体类的set方法存另一方的持久态的值即可
单向关联多对多
多对多的实现其实在关联关系上都是一对多的道理
只不过需要个中间表来建立两边对应表的中间关系
在实体类的属性配置中跟一对多是一样的 都是用到了set集合
在映射文件的配置当中需要配置要建立中间表的关系 具体如下
<set name="" table="">
<key column=""></key>
<many to many Class="" column=""></many to many>
</set>
table:加了table属性 就说明是多对多的关系, table中所写的就是所建立 中间表的名字
key:column 属性表示 当前配置类 将自己的主键放在中间表的哪一列中 里面写列名
many to many :中的column属性表示的是另外一张表将自己的主键放在中间表的哪一列中
单向关联一对一
配置一对一有两种思路
第一种是利用一对多或者多对一的关系进行配置
第二种 是直接利用one to one 一对一的标签进行配置
此时要分清主次,配关系一般配置次的一方,或者配双向。(尽可能的去配双向)
Hibernate查询
查询是持久层状态中最重要的一个部分
Hibernate也提供了相应的支持 将查询分为了三种方式
1.原生查询
2.条件查询
3.HQL查询
原生SQL查询
Hibernate提供了对sql语句直接利用的查询
但hibernate是一种ORM框架 直接操作对象的 而SQL是面向数据 面向表的
所以Hibernate 并不建议 用这种查询方式
首先从sessionFactory获得session对象
String sql ="sql语句"
通过session.createSQLQuery() 方法进行查询
条件查询
条件查询也是Hibernate提供的查询方式之一
他主要是将方法调用再组装查询条件 来进行所需要的查询。
常用到的类有
Criteria:条件查询对象查询
Restrictions:用来添加条件,封装了关系用算符的相关方法
Projections:封装了一些常用的聚合函数 比如统计 最大 最小 平均
Order排序
在什么条件都不添加的时候是查询全部数据.
通过createCriteria()方法 里面写要查询的数据表所对应的实体类
之后用add(Restrictions.eq())进行要添加条件
HQL查询
HQL查询就是Hibernate所提供的查询语言,总称为 Hibernate Query Language.
类似于SQL语言,不同的在于 SQL面向数据库 而HQL面向对象
所以SQL里写的是表名 字段名 HQL中写的是类名 属性名
SQL中支持的写法 HQL都支持 只是比SQL看起来更简洁明了
HQL区分大小写 只限于类名和属性名
HQL语法
基本语法 select 别名 from 类名 别名 where 属性名 = 值 ;