Hibernate
是一个基于JDBC
的持久层框架,功能及其强大,支持线程池、三级缓存、它根据ORM
思想设计的,利用它可以利用面向对象的方式来操作数据库,让用户不用和复杂的SQL
语言打交道。
1.讲下什么是Hibernate
?
Hibernate
是一个基于JDBC
的持久层的开源框架,它可以根据ORM利用面向对象思想来处理数据库的可能,它支持线程池,三级缓存,利用它可以大大简化开发流程,简化数据操作层的代码。
2.讲下什么是ORM
?ORM
组件有哪些?
ORM
是指对象关系模型,O是指对象object
,R是指关系Relational
,M是指映射Mapping
,是一种用面向对象方法来处理数据库的思想,可以通过控制对象的属性和方法来对数据库进行一些基本的操作,这样用户就无需和复杂的sql
语句打交道,简化了数据库的操作。
在目前ORM组件有:
JPA
,是通过注解或者XML描述对象关系表的映射关系;Hibernate
,是通过对象关系映射的配置;MyBatis
,是Apache
下面的一个开源项目,支持普通的SQL插叙,存储过程和高级映射的优秀持久层框架;DButils
、Spring
、JDBC
、Template
;- 最后就是
Spring Date
。
3.Hibernate
和JDBC
相比的优点是什么?缺点是什么?
Hibernate
是基于ORM
思想而产生的一个工具,可以实现在Java处理数据库就像操作一个个实体对象一样简单方便,实现Java
面向对象开发思想的统一,其相对于JDBC
可以大大提高开发效率,简化代码。
他的优点也给它带来了一些缺点,其最大的缺点就是性能问题,因为Hibernate
的存在,程序在访问数据库的流程又多了一个环节,性能问题是它最大的缺陷,特别是在大批量数据处理的时候,其性能与JDBC
之间约相差30%之多。
4.如何搭建一个Hibernate
的环境
- 首先需要在
Hibernate
官方网站上面去下载jar包; - 然后将
Hibernate
的文件包lib目录下面的other
和required
目录下面的jar包赋值到自己的项目里面,并右键添加进构造路径; - 设置类映射文件,这个配置文件命名是按
类名.hbm.xml
规律来的,需要和实体类放在同一个文件夹中,文件里面可以配置类和表一些映射关系,id
标签是配置主键的,property
标签可以配置类属性与表字段名,还可以配置一些更复杂的映射关系,比如一对多,多对多等等; - 设置核心配置文件,首先需要在核心配置文件里面配置数据库的驱动、数据库访问网址、数据库访问用户名和密码,然后还需要将实体类的映射文件加载进来;
- 还差最后一步就是创建一个调用
Hibernate
的工具类,HibernateUtils
。
5.说说Hibernate
的三种状态之间如何转换?
Hibernate
里面的数据的三种状态分别是瞬时态、持久态、和托管态三种状态,当数据新建new出来之后存储在缓存里面的一种状态就是瞬时态、在缓存中间的数据通过save()
或者saveOrUpdate()
方法的就会将数据写入数据库,这种数据库和缓存里面都同时存在数据的状态就是持久态,当程序调用close()
、clear()
,等方法清空缓存区后,数据就只有数据里面才有数据,这种状态就是托管态,而此时,如果调用get()
、load()
、update()
等等方法时数据就会被读取到缓存里面去,这时候数据就收恢复为持久态度,此时如果掉用delete()
方法将数据进行删除数据就会立即从数据库中消失变成瞬时态。
6.Hibernate
中session
有几种创建方式?都有那些区别?
Hibernate
中的session
有两种创建方式:
- 第一种就是
getCurrentSession()
方法,这个方法使用前需要在核心配置文件里面和线程绑定,调用它之后,它首先会到当前线程中间去寻找是否存在session
,如果不存在它就会新建一个session
,使用前它需要创建一个事务,在事务提交之后,它会自动关闭。 - 第二种就是open
session
方法,不需要任何配置,使用前也不需要开启事务,每次调用它都是在当前线程里面新建一个session
,而且在事务提交时它是不会自动关闭的,系数要手动关闭。
7.Hibernate
中有哪些缓存?都是如何配置的?(三个缓存都要说)
Hibernate
中有三种缓存:
- 第一种就是一级缓存,它在
Hibernate
中是默认开启的,属于session
级别的缓存,缓存的数据仅限当前session
来获取。 - 第二种就是二级缓存,是一种
sessionFactory
级别的缓存,可以实现session
之间的数据共享,它分为内置缓存和外置缓存,其中内置缓存是存储一些供Hibernate
自己调用系统参数,而外置缓存Hibernate
仅仅是提供了一个接口,需要利用第三方的缓存工具。配置二级缓存有点儿复杂:
a. 首先需要导包;
b. 第二步在核心配置文件里面开启二级缓存设置;
c. 第三步在核心配置文件里面指定二级缓存的供应商;
d. 最后还需要配置所需要缓存的类和集合,配置语句需要放在导入映射文件后面,且如果想缓存集合,还需要将集合里面存储的实体类同样配置缓存。 - 第三种就是三级缓存,也可以叫做查询缓存,他主要是针对HQL语句的缓存,它是依赖于二级缓存的,可以实现
session
之间相同session
语句的和查询结果的缓存。
a.首先需要配置耳机缓存,导包、开启二级缓存、指定二级缓存供应商;
b.在使用的时候无论是存还是取都需要设置setCachable()
值为true
,才可以使用。
8.说说ge
t&load
的区别
get
与load
都是数据逐渐查询语句:
get
属于积极查询,在调用get()
方法后和立即发送SQL
语句获取该对象所关联的所有数据,其查询结果是一个具体的实体类,当查询的id
不存在时,会返回一空值。load()
方法中lazy
属性的默认值是true
,属于懒加载,当程序调用后,并不会立即发送sql
语句到数据库进行数据查询,而是返回一个存储了id
属性的代理对象,只有在调用非id
之外的其他属性,才会发送SQL
语句到数据库查询数据,而且当需要查询数据数量的时候会发送count
来查询,当查询的id
不存在时,load()
方法是会直接报错。
9.如何在控制台看到Hibernate
生成并执行的sql
?
在核心配置文件里面用property
标签配置show_sql
语句为true
就可以看到Hibernate
里面生成的sql
语句
10.Hibernate
中有几种检索方式?
Hibernate
中有两种检索方法,
a. 立即检索:在调用立即检索的方法时,系统会立即向数据库发送SQL
语句;
b. 延时检索:在调用延时检索的方法是,系统不会立即向数据库发送SQL
查询语句,而是在等待用的时候才会发送SQL
语句到数据库。
11.说说save()
,flush()
,commit()
方法调用后都做了什么?
save()
:将数据写入缓存区;flush()
:将缓存区的数据写入数据库,但不清空缓存区;commit()
:将缓存区的数据写入数据库,清空缓存区,并关闭当前事务。
12.Hibernate
中怎样实现类之间的关系?(如:一对多、多对多的关系)
Hibernate
是用映射文件的方式来处理映射表之间的关系:
- 一对多:首先在一的这一方对象需要创建一个存储多方对象的
Set
集合,然后再该类的映射文件里面添加一个Property
标签,配置name
属性,并配置多方的类名和关联外键的字段名。而多的一方则是定义一个一方属性,然后在映射文件里面配置属性名和关联字段名; - 多对多:多对多时利用一个中间表来存储双方的关联外键,在双方都会添加一个对方的对象实例,并在映射文件里面配置对方的关联外键和对方的类。
13.Hibernate
是如何延迟加载?
Hibernate
中的延时加载是指数据在使用的时候才会发送SQL语句到数据库,避免了一些无意义的查询。
具体的配置就是设置lazy
属性,它有三个值:true
、false
、和extra
,其中true
是延时加载,false
是立即加载,而extra
则会更加的延时加载,在查询指定记录数量时会发送count()
函数,而不是查询所有记录。
14.谈谈Hibernate
中inverse
的作用?
inverse
是反转的意思,在Hibernate
中是配置关联数据库表的外键数据维护权,它有两个属性一个是true
,一个是false
,如果是true
则会将外键数据的维护权交给另一方来维护,只有在对象与外键关联的属性值发生变化时才会修改外键值,如果是false
则是自己来维护外键数据。
15.MySQL
默认的事务隔离级别是多少?JDBC
如何修改?Hibernate
如何修改?
READ UNCOMMITTED
:脏读、不可重复读、虚读有可能发生;READ COMMITTED
:避免脏读,不可重复读、虚读有可能发生;REPEATABLE READ
:避免脏读、不可重复读的发生,虚读有可能发生。SERIALIZABLE
:避免脏读、不可重复读、虚读的发生。JDBC
中:connection.setTransactionIsolation()
方法来设置。Hibernate
中是在核心配置文件里面配置isolation
的值来修改事务的隔离级别<property name="Hibernate.connection.isolation">4</property>
16.事务的特性有哪些?
- 原子性:事务是数据库的逻辑处理单位,事务中的操作要不就全部完成,要不就是全部都没有完成;
- 一致性:因为事务对数据的操作只有完成与不完成两种,所以数据库中的数据就具备前后的一致性,从一个一致的状态到另一个一致的状态,这就是数据库的一致性;
- 隔离性:事务与事务之间是相互隔离互不干扰的;
- 持久性:事务一旦提交,其对数据的影响就是持久性的。
17.什么是脏读,不可重复读,幻读
- 脏读是指一个还未提交的事务,读取到了另一个还会提交事务里面的数据。
- 不可重复读是指,一个还未提交的事务,读取到了其他事务里面已经提交导数据库里面的修改记录的数据;
- 幻度也叫虚度,是指一个还未提交的事务,读取到了其他事务里面已经提交到数据库里面的新建记录的数据。
18.说说连接池的原理
在访问数据库中,与数据的连接对象是一种比较耗费资源的操作,而很多时候我们在创建一个连接之后仅仅处理少量的数据之后就将连接关闭的行为是一种资源浪费,所以连接池的主要任务就是负责管理、分配、创建换释放连接对象,提高连接对象的复用次数,在配置连接池的时候会配置一个最大连接数量和最小连接数量,当连接对象的数量叫低的时候会创建连接对象,当连接有连接对象长期没有被使用后,也会释放连接对象,释放资源。
19.说说HQL
和QBC
,项目中都是怎么用的?
HQL
是描述对象操作的一种语言:可以类似SQL
操作那样用语句来操作数据库,它的语法和SQL比较类似但是操作的对象从表名、字段名变成了对象属性名。
- 分页操作,调用
setFirstResult
和setMaxResult
方法来设置起始位置和偏移量; - 排序,类似
SQL
语言那样用order by
来对查询结果进行排序; - 绑定参数:利用
:变量名
的形式在HQL
语言里面确定需要传入参数的位置,然后利用查询对象的方法来传入具体的值。 - 命名查询,需要在配置文件里面设置查询
HQL
语句,然后再程序里面加载查询语句; - 获取结果,如果结果是一个集合那么就用
list()
方法来获取,如果单个的值就用uniqueResult
来获取。QBC
是面向对象的条件查询语句 - 调用
session.creatCriteria(.Class)
方法传入参数,获取结果的形式和HQL
语言一样的; - 分页查询与
HQL
类似需要调用setFirstResult
和setMaxResult
语句来设置起始点和偏移量; - 排序需要调用
addOrder
方法,传入一个Order
对象; - 条件查询利用
add
方法,传入一个Restriction
对象来设置条件; - 离线查询,离线查询在设置查询条件的时候是不需要获取
session
对象,这样对于那些查询条件比较复杂的查询可以节省很多的时间,是用方法是获取一个条件查询对象DetachedCriteria
,类似普通QBC
查询那样设置查询条件。
20.说说悲观锁和乐观锁?
在QBC
并行处理数据的时候为了避免出现并发问题可以采用两种方式来解决这个问题:
- 悲观锁,其默认是一定会有其他的事务来修改当前事务正在处理的数据,所以在其处理数据的时候默认利用
for update
语句来讲当前记录锁住;在Hibernate
里面利用get
语句来设置读取模式为lockOptions.UPGRADE
;- 乐观锁的实现原理是在每一个需要乐观锁的表中添加一个
version
字段,这个字段里面存储的是当前记录的修改版本,当程序提交修改数据的时候会自动将当前版本+1,然后载荷数据库中的版本比对,如果发现数据库中的版本不小于自身修改版本就会不予修改。
- 乐观锁的实现原理是在每一个需要乐观锁的表中添加一个