1.什么是Hibernate
Hibernate是一种ORM框架,全称为 Object_Relative DateBase-Mapping,在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象。
2.为什么使用Hibernate
使用Hibernate框架就不用我们写很多繁琐的SQL语句。Hibernate实现了ORM,能够将对象映射成数据库表,从而简化我们的开发!
3.工作原理
- 读取并解析配置文件
- 读取并解析映射信息,创建SessionFactory
- 打开Sesssion
- 创建事务Transation
- 持久化操作
- 提交事务
- 关闭Session
- 关闭SesstionFactory
4.懒加载
通过设置属性lazy进行设置是否需要懒加载。
当Hibernate在查询数据的时候,数据并没有存在于内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
5.如何实现类之间的关系
它们通过配置文件中的many-to-one、one-to-many、many-to-many来实现类之间的关联关系的。
6.临时/瞬时状态
当我们直接new出来的对象就是临时/瞬时状态的
- 该对象还没有被持久化【没有保存在数据库中】
- 不受Session的管理
7.持久化状态
当保存在数据库中的对象就是持久化状态了
- 当调用session的save/saveOrUpdate/get/load/list等方法的时候,对象就是持久化状态
- 在数据库有对应的数据
- 受Session的管理
- 当对对象属性进行更改的时候,会反映到数据库中!
8.游离化状态
当Session关闭了以后,持久化的对象就变成了游离状态了
- 不处于session的管理
- 数据库中有对应的记录
9.状态转化
new出来的对象是瞬时状态 -> 保存到数据库中(受Session管理)就是持久化状态 -> 将session close掉就是游离状态
10.检索方式优缺点
立即检索:
-
优点: 对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象;
-
缺点: 1.select语句太多;2.可能会加载应用程序不需要访问的对象白白浪费许多内存空间;
-
立即检索:lazy=false;
延迟检索:
-
优点: 由应用程序决定需要加载哪些对象,可以避免可执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并且能节省内存空间;
-
缺点: 应用程序如果希望访问游离状态代理类实例,必须保证他在持久化状态时已经被初始化;
-
延迟加载:lazy=true;
迫切左外连接检索:
-
优点: 1对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地冲一个对象导航到与它关联的对象。2使用了外连接,select语句数目少;
-
缺点: 1 可能会加载应用程序不需要访问的对象,白白浪费许多内存空间;2复杂的数据库表连接也会影响检索性能;
-
预先抓取: fetch=“join”
11.缓存机制
一级缓存:
-
Hibenate中一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数! 只在session范围有效! Session关闭,一级缓存失效!
-
只要是持久化对象状态的,都受Session管理,也就是说,都会在Session缓存中!
-
Session的缓存由hibernate维护,用户不能操作缓存内容; 如果想操作缓存内容,必须通过hibernate提供的evit/clear方法操作。
二级缓存:
-
二级缓存是基于应用程序的缓存,所有的Session都可以使用
-
Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影响代码。
-
如果用户觉得hibernate提供的框架框架不好用,自己可以换其他的缓存框架或自己实现缓存框架都可以。
-
Hibernate二级缓存:存储的是常用的类
12.SessionFactory是线程安全的吗
SessionFactory 是Hibrenate单例数据存储和线程安全的,以至于可以多线程同时访问。一个SessionFactory 在启动的时候只能建立一次。SessionFactory应该包装各种单例以至于它能很简单的在一个应用代码中储存。
13.get 和 load的区别
-
get如果没有找到会返回null, load如果没有找到会抛出异常。
-
get会先查一级缓存, 再查二级缓存,然后查数据库;load会先查一级缓存,如果没有找到,就创建代理对象, 等需要的时候去查询二级缓存和数据库。
14.merge的含义
-
如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例
-
如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例,最后返回该持久实例
-
用户给出的这个对象没有被关联到session上,它依旧是脱管的
15.persist 和 save的区别
-
persist不保证立即执行,可能要等到flush;
-
persist不更新缓存;
-
save, 把一个瞬态的实例持久化标识符,及时的产生,它要返回标识符,所以它会立即执行Sql insert
-
使用 save() 方法保存持久化对象时,该方法返回该持久化对象的标识属性值(即对应记录的主键值);
-
使用 persist() 方法来保存持久化对象时,该方法没有任何返回值。
16.可否将实体类定义为final
可以将Hibernate的实体类定义为final类,但这种做法并不好。因为Hibernate会使用代理模式在延迟关联的情况下提高性能,如果你把实体类定义成final类之后,因为 Java不允许对final类进行扩展,所以Hibernate就无法再使用代理了,如此一来就限制了使用可以提升性能的手段
17.hibernate.cfg.xml
如果使用Intellij Idea生成的Hibernate可以指定生成出主配置文件hibernate.cfg.xml,它是要放在src目录下的
如果不是自动生成的,我们可以在Hibernate的hibernate-distribution-3.6.0.Final\project\etc这个目录下可以找到
18.Configuration
配置管理类:主要管理配置文件的一个类
它拥有一个子类AnnotationConfiguration,也就是说:我们可以使用注解来代替XML配置文件来配置相对应的信息
-
Configure
加载主配置文件的方法如果指定参数,那么加载参数的路径配置文件
如果不指定参数,默认加载src/目录下的hibernate.cfg.xml
-
buildSessionFactory
用于创建Session工厂
19.SessionFactory
SessionFactory–>Session的工厂,也可以说代表了hibernate.cfg.xml这个文件…hibernate.cfg.xml的就有这么一个节点
- openSession
创建一个Session对象 - getSessionFactory
创建Session对象或取出Session对象
20.Session
Session是Hibernate最重要的对象,Session维护了一个连接(Connection),只要使用Hibernate操作数据库,都需要用到Session对象
21.更新操作
我们在快速入门中使用到了save(Objcet o)方法,调用了这个方法就把对象保存在数据库之中了。Session对象还提供着其他的方法来进行对数据库的更新
-
session.save(obj); 【保存一个对象】
-
session.update(obj); 【更新一个对象】
-
session.saveOrUpdate(obj); 【保存或者更新的方法】
-
没有设置主键,执行保存;
-
有设置主键,执行更新操作;
-
如果设置主键不存在报错!
-
22.主键查询
通过主键来查询数据库的记录,从而返回一个JavaBean对象
-
session.get(javaBean.class, int id); 【传入对应的class和id就可以查询】
-
session.load(javaBean.class, int id); 【支持懒加载】
23.HQL查询
HQL:hibernate query language 即hibernate提供的面向对象的查询语言
- 查询的是对象以及对象的属性【它查询的是对象以及属性,因此是区分大小写的!】。
SQL:Struct query language 结构化查询语言
- 查询的是表以及列【不区分大小写】
HQL是面向对象的查询语言,可以用来查询全部的数据!
24.QBC查询
QBC查询: query by criteria 完全面向对象的查询
从上面的HQL查询,我们就可以发现:HQL查询是需要SQL的基础的,因为还是要写少部分的SQL代码….QBC查询就是完全的面向对象查询…但是呢,我们用得比较少
25.本地SQL查询
有的时候,如果SQL是非常复杂的,我们不能靠HQL查询来实现功能的话,我们就需要使用原生的SQL来进行复杂查询了!
但是呢,它有一个缺陷:它是不能跨平台的…因此我们在主配置文件中已经配置了数据库的“方言“了。
26.beginTransaction
开启事务,返回的是一个事务对象….Hibernate规定所有的数据库操作都必须在事务环境下进行,否则报错!
27.主配置文件
-
数据库信息
常用的配置信息都可以在hibernate.properties文件中找到
-
其他参数
-
create-drop 每次在创建sessionFactory时候执行创建表。当调用sesisonFactory的close方法的时候,删除表!
-
create 每次都重新建表; 如果表已经存在就先删除再创建
-
update 如果表不存在就创建; 表存在就不创建;
-
validate (生成环境时候) 执行验证: 当映射文件的内容与数据库表结构不一样的时候就报错!
-
-
加载映射文件
-
值得注意的是:mapping的属性使用的是resource!
-
加载映射文件其实我们可以在程序中加载,不一定在配置文件中配置….一般地,我们在测试的时候一般使用程序的方式去加载映射文件【方便】
-
那么怎么在程序中加载映射文件呢?
-
在Configuration对象中提供了addClass()的方法。
-
一般地我们的映射配置文件和JavaBean对象是放在同一个包下的。并且映射文件的命名是有规范的。因此Hibernate是可以通过提供的JavaBean对象从而找到相对应的映射文件!
-
28.映射配置文件
映射文件: 映射一个实体类对象; 描述一个对象最终实现可以直接保存对象数据到数据库中
通常地,我们都是一个JavaBean对象对应一个映射配置文件,并且配置文件和JavaBean对象是放在同一个目录下的
-
hibernate-mapping节点
常用的属性:-
package【要映射的对象所在的包(可选,如果不指定,此文件所有的类都要指定全路径)】
-
auto-import
-
默认为true, 在写hql的时候自动导入包名
-
如果指定为false, 再写hql的时候必须要写上类的全名
-
-
-
class节点
- class 映射某一个对象的(一般情况,一个对象写一个映射文件,即一个class节点)
常用的属性:
-
name【指定要映射的对象的类型】
-
table【指定对象对应的表】
如果没有指定,默认与对象名称一样
-
property
property是普通属性的映射,即JavaBean普通的成员变量属性就使用property来描述!常用的属性:
-
name 指定对象的属性名称
-
column 指定对象属性对应的表的字段名称
如果不写默认与对象属性一致。
-
length 指定字符的长度, 默认为255
-
type 指定映射表的字段的类型,如果不指定会匹配属性的类型
java类型: 必须写全名【例:java.lang.String】
hibernate类型: 直接写类型,都是小写
值得注意的是:如果列名称为数据库关键字,需要用反引号或改列名。当然啦,我们一般不使用关键字来作为列名
-
-
id节点
id是主键映射….-
name 指定对象的属性名
-
column 指定对象属性对应的表的字段名称
节点下还有子节点
主键的自动生成策略:
-
identity 自增长(mysql,db2)
-
sequence 自增长(序列), oracle中自增长是以序列方法实现**
-
native 自增长【会根据底层数据库自增长的方式选择identity或sequence】
-
如果是mysql数据库, 采用的自增长方式是identity
-
如果是oracle数据库, 使用sequence序列的方式实现自增长
-
-
increment 自增长(会有并发访问的问题,一般在服务器集群环境使用会存在问题。)
指定主键生成策略为手动指定主键的值
- assigned
指定主键生成策略为UUID生成的值
- uuid
-
-
composite-id节点
主键一般分为两种:-
单列主键
-
多列复合主键
-