1、Hibernate的概念
Hibernate是对JDBC进行轻量级封装的ORM(Object Relation Mapping)框架,充当项目的持久层。Hibernate的基础是java的反射机制。
2、Hibernate的5个核心接口:
Configuration接口:配置并启动Hibernate,同时创建SessionFactory对象。
SessionFactory接口:初始化Hibernate,创建session 对象。线程安全,二级缓存。
Session接口:负责保存、更新、删除、加载和查询对象;线程不安全,轻量级、一级缓存。
Transaction接口:管理事务。
Query接口和Criteria接口:执行数据库的查询。
3、Hibernate的工作原理
(1)、读取并解析hibernate.cfg.xml配置文件
Configuration config = new Configuration().configure();
(2)、读取并解析映射信息,
hibernate.cfg.xml中的读取并解析映射信息
(3)、创建SessionFactory
SessionFactory sf = config.buildSessionFactory();
(4)、打开Sesssion
Session session = sf.openSession();
(5)、创建事务Transation
Transaction tx = session.beginTransaction();
(6)、持久化操作
persistent operate操作数据
(7)、提交事务
tx.commit();
(7)、关闭Session
(8)、关闭SesstionFactory
4、Hibernate的优点(为什么要用Hibernate)
(1)、封装了JDBC,简化了很多重复性的代码。
(2)、简化的DAO层的编写工作,使开发更加对象化。
(3)、移植性好,支持各种数据库。如何换数据库只需要在配置文件中更改配置就可以 了,不需要更改Hibernate代码。
(4)、性能好,是一个轻量级的框架。
(5)、hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
5、Hibernate的缺点
(1)、由于对持久层封装过于完整,导致开发人员无法对SQL语句进行优化。
(2)、Hibernate封装了JDBC,所以没有JDB直接访问数据库的效率高。
(3)、框架中使用了ORM原则,导致项目的配置过多,一旦遇到大型的项目,比如300张表以上,配置文件和内容是非常庞大的,另外,DTO满天飞,性能和维护问题随之而来。
(4)、如果项目中各个表中关系复杂,表之间的关系很多,在很多地方把lazy都设置false,会导致数据查询和加载很慢,尤其是级联查询的时候。
(5)、Hibernate在批量数据处理时有弱势,对于批量的修改,删除,不适合用Hibernate,这也是ORM框架的弱点。
6、Hibernate中对象的3个状态
瞬时状态(临时态):刚用new语句创建,还没被持久化,数据库中也没有与之对应的记录,并且不处于session缓存中。(处于临时态的对象称为临时对象)。
持久态:已经被持久化,并且加入到Session缓存中。(处于持久态的对象称为持久化对象)
游离态(脱管状态):已经被持久化,但不再处于Session缓存中。(处于游离态的对象称为游离对象)。
三种状态之间的转换
7、Hibernate的缓存机制
(1)、为什么要用hibernate缓存?
①、hibernate是一个持久层框架,经常访问物理数据库;
②、为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。
③、缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
(2)、hibernate的缓存原理
Hibernate的缓存包括一级缓存(Session)和二级缓存(SessionFactory)。
一级缓存:
①、概念:Session级缓存,我们去查询对象的时候,首先到一级缓存去取数据,如果有,则不到数据库中取,如果没有则到数据库中取,同时在一级缓存中放入对象。
②、特点:a.save,update,saveOrUpdate,load,get,list会向一级缓存存数据; b.get,load会从一级缓取数据:list不会从一级缓存取数据;c.一级缓存不需要配置,就可以使用,它本身没有保护机制,所以我们程序员要考 虑这个问题,我们可以用 evict 或者 clear来清除session缓存中对象. evict 是清除一个对象,clear是清除所有的session缓存对象;d.session级缓存中对象的生命周期, 当session关闭后,就自动销毁.
③、启用方式:只要通过Session接口来执行保存,更新,删除,加载,查询,Hibernate就会启用一级缓存,对于批量操作,如不希望启用一级缓存,直接通过JDBCAPI来执行。
二级缓存:
①、由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。
②、因为一级缓存有限(生命周期短),所以我们需要二级缓存(SessionFactory缓存)来弥补这个问题。同时,二级缓存需要配置。它是交给第三方去处理,常见的Hashtable , OSCache , EHCache。
③、什么样的数据适合存放到第二级缓存中?
1)很少被修改的数据
2) 不是很重要的数据,允许出现偶尔并发的数据
3) 不会被并发访问的数据
4) 常量数据
④、不适合存放到第二级缓存的数据?
- 经常被修改的数据
- 绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发
- 与其他应用共享的数据。
⑤、启用方式:用户可以再单个类或类的单个集合的粒度上配置第二级缓存,如果类的实例被经常读,但很少被修改,就可以考虑使用二级缓存,只有为某个类或集合配置了二级缓存,Hibernate在运行时才会把它的实例加入到二级缓存中。
8、Hibernate中的类之间的关系及实现方式
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many。
9、Hibernate中的懒加载
(1)概述:当我们查询一个对象的时候,在默认情况下,返回的只是该对象的普通属性,当用户去使用对象属性时,才会向数据库发出再一次的查询.这种现象我们称为 lazy现象。
(2)懒加载的解决方案
①、使用Hibernate.initized(代理对象)显式初始化。
②、修改对象关系文件 lazy 改写 lazy=false。
③、通过过滤器(web项目) openSessionInView
(获取session的方式必须使用getCurrentSession;
关闭session的方式:HibernateUtil.closeCurrentSession();)。
10、Hibernate主键生成策略
Hibernate的主键映射
主键名称 作用
increment 代理主键,适合于所有数据库,由hibernate维护主键自增,和底层数据库无关,但是不适合于2个或以上hibernate进程
identity 代理主键,适合于Mysql或ms sql server等支持自增的dbms,主键值不由hibernate维护
sequence 代理主键,适合于oracle等支持序列的dbms,主键值不由hibernate维护,由序列产生
native 代理主键,根据底层数据库的具体特性选择适合的主键生成策略,如果是mysql或sqlserver,选择identity,如果是oracle,选择sequence
hilo 代理主键,hibernate把特定表的字段作为hign值,生成主键值
uuid 代理主键,hibernate采用uuid 128位算法生成基于字符串的主键值
assigned 由应用程序负责生成主键标识符,往往使用在数据库中没有代理主键,使用的主键与业务相关的情况
seqhilo sequence和hilo的结合,hilo的高位由sequence产生,所以也需要底层数据库的支持
Hibernate主键生产策略的配置:在hibernate.cfg.xml配置文件中的中配置
11、Hibernate中的级联
(1)、概念:级联是指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作。
(2)、级联的取值及含义
取值 含义
all 代表在所有的情况下都执行级联操作
none 在所有情况下都不执行级联操作
save-update 在保存和更新的时候执行级联操作
delete 在删除的时候执行级联操作
(3)
12、Hibernate中的查询语句
13、POJO
(1)、概念:在使用hibernate时,要求和数据库的某张表相互映射的那个java类,
是一个POJO类,一般放在com.xxx.domain包下,POJO类翻译过来就是:简单的Java对象(Plain Ordinary Java Objects)实际就是普通JavaBeans,使用POJO名称是为了避免和EJB混淆起来。
(3)、POJO的特征:
①、有一个主键属性,用于唯一标识该对象。
②、有其它的属性。
③、有对各个属性操作的get/set方法。
④、属性一般是private修饰。
⑤、一定有一个无参的构造函数(用于hibernate框架反射用.)
14、Hibernate中get()和load()的区别
区别 get() load()
加载方式 立即加载 延迟加载
缓存中没对象 返回的是pojo对象 返回的是代理对象
当未能发现符合条件的记录 get方法返回null load方法会抛出一个ObjectNotFoundException
15、Hibernate的检索策略
Hibernate提出了检索策略的概念,即在建立关联关系的情况下,在加载当前对象时,对关联对象的检索策略。合理设置关联关系,可以提高软件的运行效率。
常见检索策略包含:立即检索,延迟检索,迫切连接检索。
检索策略 立即检索 延迟检索 迫切连接检索
实现方式 将元素的lazy设置为false 将元素的lazy设置为true 将元素的fetch设置为join
检索方式 立即初始化与当前对象关联对象 不立即初始化与当前对象关联对象。而是为关联对象创建一个代理对象,只有代理对象的其他属性被请求才初始化该代理对象 立即初始化与当前对象关联的对象,该检索只对session的load()和get()方法有效。当同时使用延时检索和迫切左外连接检索时,后者覆盖前者
优点 即使当前处于游离态,也可以很方便的从当前对象导航到与之关联的对象 有程序动态控制对象加载,可以避免执行不必要的select语句加载不需要的对象 对应用程序完全透明,不管对象处于那种状态,程序都可以方便地从一个对象导航到与它关联的对象;使用了外连接,select语句数目少
缺点 select语句的数目太多,需要频繁的访问数据库,会影响检索性能 当访问处于游离状态的对象时,必须保证关联对象已经被初始化
可能加载不需要访问的对象,浪费内存空间;复杂的数据库连接也会影响检索性能。
三种检索策略的运行机制
检索策略的类型 类别级 关联级别
立即检索 立即加载检索方法制定的对象 立即加载与检索方指定的对象的关联对象,可以设定批量检索数量
延迟检索 延迟加载检索方法制定的对象 延迟加载与检索方指定的对象的关联对象,可以设定批量检索数量
迫切左联接检索 不适用 通过左外连接加载与检索方法指定的对象的关联对象
Lazy和fetch配合使用的组合问题
对应关系 lazy属性
(默认值为true) fetch属性
(默认值为select) 检索策略
一对多
多对多 true select 采用延迟检索,默认的检索策略
false select 采用立即检索,使用二级缓存时
extra select 采用加强延迟检索
未设置(true) join 采用迫切左连接检索策略
多对一
一对一 (默认值为proxy) (默认值为select) 检索策略
proxy select 采用延迟检索
no-proxy select 无代理延迟检索
false select 立即检索
未设置(proxy) join 迫切左外连接检索
16、Hibernate中inverse和cascade的区别
inverse cascade
负责控制关系,默认为false,也就是关系的两端都能控制,但这样会造成一些问题,更新的时候会因为两端都控制关系,于是重复更新。一般来说有一端要设为true。 负责控制关联对象的级联操作,包括更新、删除等,也就是说对一个对象进行更新、删除时,其它对象也受影响,比如我删除一个对象,那么跟它是多对一关系的对象也全部被删除。
17、openSession()与getCurrentSession()的区别
(1)、openSession() 是获取一个新的session;
(2)、getCurrentSession () 获取和当前线程绑定的session,换言之,在同一个线程中,
我们获取的session是同一session,这样可以利于事务控制;
如果希望使用getCurrentSession,需要配置 hibernate.cfg.xml中配置:
thread
(3)、选择原则:
①如果需要在同一线程中,保证使用同一个Session则,使用getCurrentSession()
②如果在一个线程中,需要使用不同的Session,则使用openSession()
(4)、通过 getCurrentSession() 获取的session在事务提交后,会自动关闭,
通过openSession()获取的session则必须手动关闭,
(5)、如果是通过getCurrentSession()获取Sesssion ,进行查询需要事务提交。
18、JDBC和Hibernate的区别
区别 JDBC Hibernate
SQL语言 基于关系型数据库的标准SQL语言 HQL语言
操作的对象 操作数据,将数据通过SQL语句直接传送到数据库中执行 操作持久化对象,由底层持久化对象的数据更新到数据库中
数据状态 数据是瞬时态的 数据是可持久的