Hibernate知识点汇总

Hibernate是一个基于JDBC的持久层框架,功能及其强大,支持线程池、三级缓存、它根据ORM思想设计的,利用它可以利用面向对象的方式来操作数据库,让用户不用和复杂的SQL语言打交道。

1.讲下什么是Hibernate

Hibernate是一个基于JDBC的持久层的开源框架,它可以根据ORM利用面向对象思想来处理数据库的可能,它支持线程池,三级缓存,利用它可以大大简化开发流程,简化数据操作层的代码。

2.讲下什么是ORM?ORM组件有哪些?

ORM是指对象关系模型,O是指对象object,R是指关系Relational,M是指映射Mapping,是一种用面向对象方法来处理数据库的思想,可以通过控制对象的属性和方法来对数据库进行一些基本的操作,这样用户就无需和复杂的sql语句打交道,简化了数据库的操作。
在目前ORM组件有:

  1. JPA,是通过注解或者XML描述对象关系表的映射关系;
  2. Hibernate,是通过对象关系映射的配置;
  3. MyBatis,是Apache下面的一个开源项目,支持普通的SQL插叙,存储过程和高级映射的优秀持久层框架;
  4. DButilsSpringJDBCTemplate
  5. 最后就是Spring Date

3.HibernateJDBC相比的优点是什么?缺点是什么?

Hibernate是基于ORM思想而产生的一个工具,可以实现在Java处理数据库就像操作一个个实体对象一样简单方便,实现Java面向对象开发思想的统一,其相对于JDBC可以大大提高开发效率,简化代码。

他的优点也给它带来了一些缺点,其最大的缺点就是性能问题,因为Hibernate的存在,程序在访问数据库的流程又多了一个环节,性能问题是它最大的缺陷,特别是在大批量数据处理的时候,其性能与JDBC之间约相差30%之多。

4.如何搭建一个Hibernate的环境

  1. 首先需要在Hibernate官方网站上面去下载jar包;
  2. 然后将Hibernate的文件包lib目录下面的otherrequired目录下面的jar包赋值到自己的项目里面,并右键添加进构造路径;
  3. 设置类映射文件,这个配置文件命名是按类名.hbm.xml规律来的,需要和实体类放在同一个文件夹中,文件里面可以配置类和表一些映射关系,id标签是配置主键的,property标签可以配置类属性与表字段名,还可以配置一些更复杂的映射关系,比如一对多,多对多等等;
  4. 设置核心配置文件,首先需要在核心配置文件里面配置数据库的驱动、数据库访问网址、数据库访问用户名和密码,然后还需要将实体类的映射文件加载进来;
  5. 还差最后一步就是创建一个调用Hibernate的工具类,HibernateUtils

5.说说Hibernate的三种状态之间如何转换?

Hibernate里面的数据的三种状态分别是瞬时态、持久态、和托管态三种状态,当数据新建new出来之后存储在缓存里面的一种状态就是瞬时态、在缓存中间的数据通过save()或者saveOrUpdate()方法的就会将数据写入数据库,这种数据库和缓存里面都同时存在数据的状态就是持久态,当程序调用close()clear(),等方法清空缓存区后,数据就只有数据里面才有数据,这种状态就是托管态,而此时,如果调用get()load()update()等等方法时数据就会被读取到缓存里面去,这时候数据就收恢复为持久态度,此时如果掉用delete()方法将数据进行删除数据就会立即从数据库中消失变成瞬时态。

6.Hibernatesession有几种创建方式?都有那些区别?

Hibernate中的session有两种创建方式:

  1. 第一种就是getCurrentSession()方法,这个方法使用前需要在核心配置文件里面和线程绑定,调用它之后,它首先会到当前线程中间去寻找是否存在session,如果不存在它就会新建一个session,使用前它需要创建一个事务,在事务提交之后,它会自动关闭。
  2. 第二种就是opensession方法,不需要任何配置,使用前也不需要开启事务,每次调用它都是在当前线程里面新建一个session,而且在事务提交时它是不会自动关闭的,系数要手动关闭。

7.Hibernate中有哪些缓存?都是如何配置的?(三个缓存都要说)

Hibernate中有三种缓存:

  1. 第一种就是一级缓存,它在Hibernate中是默认开启的,属于session级别的缓存,缓存的数据仅限当前session来获取。
  2. 第二种就是二级缓存,是一种sessionFactory级别的缓存,可以实现session之间的数据共享,它分为内置缓存和外置缓存,其中内置缓存是存储一些供Hibernate自己调用系统参数,而外置缓存Hibernate仅仅是提供了一个接口,需要利用第三方的缓存工具。配置二级缓存有点儿复杂:
    a. 首先需要导包;
    b. 第二步在核心配置文件里面开启二级缓存设置;
    c. 第三步在核心配置文件里面指定二级缓存的供应商;
    d. 最后还需要配置所需要缓存的类和集合,配置语句需要放在导入映射文件后面,且如果想缓存集合,还需要将集合里面存储的实体类同样配置缓存。
  3. 第三种就是三级缓存,也可以叫做查询缓存,他主要是针对HQL语句的缓存,它是依赖于二级缓存的,可以实现session之间相同session语句的和查询结果的缓存。
    a.首先需要配置耳机缓存,导包、开启二级缓存、指定二级缓存供应商;
    b.在使用的时候无论是存还是取都需要设置setCachable()值为true,才可以使用。

8.说说get&load的区别

getload都是数据逐渐查询语句:

  1. get属于积极查询,在调用get()方法后和立即发送SQL语句获取该对象所关联的所有数据,其查询结果是一个具体的实体类,当查询的id不存在时,会返回一空值。
  2. 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属性,它有三个值:truefalse、和extra,其中true是延时加载,false是立即加载,而extra则会更加的延时加载,在查询指定记录数量时会发送count()函数,而不是查询所有记录。

14.谈谈Hibernateinverse的作用?

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.事务的特性有哪些?

  1. 原子性:事务是数据库的逻辑处理单位,事务中的操作要不就全部完成,要不就是全部都没有完成;
  2. 一致性:因为事务对数据的操作只有完成与不完成两种,所以数据库中的数据就具备前后的一致性,从一个一致的状态到另一个一致的状态,这就是数据库的一致性;
  3. 隔离性:事务与事务之间是相互隔离互不干扰的;
  4. 持久性:事务一旦提交,其对数据的影响就是持久性的。

17.什么是脏读,不可重复读,幻读

  • 脏读是指一个还未提交的事务,读取到了另一个还会提交事务里面的数据。
  • 不可重复读是指,一个还未提交的事务,读取到了其他事务里面已经提交导数据库里面的修改记录的数据;
  • 幻度也叫虚度,是指一个还未提交的事务,读取到了其他事务里面已经提交到数据库里面的新建记录的数据。

18.说说连接池的原理

在访问数据库中,与数据的连接对象是一种比较耗费资源的操作,而很多时候我们在创建一个连接之后仅仅处理少量的数据之后就将连接关闭的行为是一种资源浪费,所以连接池的主要任务就是负责管理、分配、创建换释放连接对象,提高连接对象的复用次数,在配置连接池的时候会配置一个最大连接数量和最小连接数量,当连接对象的数量叫低的时候会创建连接对象,当连接有连接对象长期没有被使用后,也会释放连接对象,释放资源。

19.说说HQLQBC,项目中都是怎么用的?

HQL是描述对象操作的一种语言:可以类似SQL操作那样用语句来操作数据库,它的语法和SQL比较类似但是操作的对象从表名、字段名变成了对象属性名。

  • 分页操作,调用setFirstResultsetMaxResult方法来设置起始位置和偏移量;
  • 排序,类似SQL语言那样用order by来对查询结果进行排序;
  • 绑定参数:利用:变量名的形式在HQL语言里面确定需要传入参数的位置,然后利用查询对象的方法来传入具体的值。
  • 命名查询,需要在配置文件里面设置查询HQL语句,然后再程序里面加载查询语句;
  • 获取结果,如果结果是一个集合那么就用list()方法来获取,如果单个的值就用uniqueResult来获取。
    QBC是面向对象的条件查询语句
  • 调用session.creatCriteria(.Class)方法传入参数,获取结果的形式和HQL语言一样的;
  • 分页查询HQL类似需要调用setFirstResultsetMaxResult语句来设置起始点和偏移量;
  • 排序需要调用addOrder方法,传入一个Order对象;
  • 条件查询利用add方法,传入一个Restriction对象来设置条件;
  • 离线查询,离线查询在设置查询条件的时候是不需要获取session对象,这样对于那些查询条件比较复杂的查询可以节省很多的时间,是用方法是获取一个条件查询对象DetachedCriteria,类似普通QBC查询那样设置查询条件。

20.说说悲观锁和乐观锁?

QBC并行处理数据的时候为了避免出现并发问题可以采用两种方式来解决这个问题:

  • 悲观锁,其默认是一定会有其他的事务来修改当前事务正在处理的数据,所以在其处理数据的时候默认利用for update语句来讲当前记录锁住;在Hibernate里面利用get语句来设置读取模式为lockOptions.UPGRADE
    • 乐观锁的实现原理是在每一个需要乐观锁的表中添加一个version字段,这个字段里面存储的是当前记录的修改版本,当程序提交修改数据的时候会自动将当前版本+1,然后载荷数据库中的版本比对,如果发现数据库中的版本不小于自身修改版本就会不予修改。
-------------本文结束感谢您的阅读-------------