第一部分 Java基础
第二部分 Java进阶

Java Hibernate面试题

1、简述一下hibernate的开发流程?

● 第一步:加载hibernate的配置文件,读取配置文件的参数(jdbc连接参数,数据库方言,hbm表与对象关系映射文件)

● 第二步:创建SessionFactory会话工厂(内部有连接池)

● 第三步:打开session获取连接,构造session对象(一次会话维持一个数据连接,也是一级缓存)

● 第四步:开启事务

● 第五步:进行操作

● 第六步:提交事务

● 第七步:关闭session(会话)将连接释放

● 第八步:关闭连接池

2、hibernate 中对象的三种状态?

瞬时态(临时态、自由态):不存在持久化标识OID,尚未与Hibernate Session关联对象,被认为处于瞬时态,失去引用将被JVM回收。

持久态:存在持久化标识OID,与当前session有关联,并且相关联的session没有关闭,并且事务未提交。

脱管态(离线态、游离态):存在持久化标识OID,但没有与当前session关联,脱管状态改变hibernate不能检测到。

3、hibernate的一级缓存机制?

● Hibernate一级缓存(Session的缓存):

Session实现了第一级Cache,属于事务级数据缓冲。一旦事务结束,缓存随之失效。一个Session的生命周期对应一个数据库事务或一个程序事务。

Session-Cache总是被打开并且不能被关闭的。

Session-Cache保证一个Session中两次请求同一个对象时,取得的对象是同一个Java实例,有时它可以避免不必要的数据冲突。

在对于同一个对象进行循环引用时,不至于产生堆栈溢出。

当数据库事务结束时,对于同一数据表行,不会产生数据冲突。因为对于数据库中的一行,最多有一个对象来表示它。

一个事务中可能会有很多个处理单元,在每一个处理单元中做的操作都会立即被其他的数据单元得知。

4、Hibernate二级缓存(SessionFactory的缓存)?

● 二级缓存是SessionFactory范围内的缓存,所有的Session共享同一个二级缓存。在二级缓存中保存持久化实例的散装形式的数据。

● 持久化不同的数据需要不同的Cache策略,比如一些因素将影响Cache策略的选择:数据的读/写比例、数据表是否能被其他的应用程序所访问等。

● 设置Hibernate二级缓存需要分两步:首先,确认使用什么数据并发策略。然后,配置缓存过期时间并设置Cache提供器。

5、Hibernate的查询方式有哪些?

Hibernate的查询方式常见的主要分为三种:HQL,QBC(命名查询),以及使用原生SQL查询(SqlQuery)

6、Hibernate和Mybatis的区别?

● 两者相同点:

Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。

Hibernate和MyBatis都支持JDBC和JTA事务处理。

● Mybatis优势:

MyBatis可以进行更为细致的SQL优化,可以减少查询字段。

MyBatis容易掌握,而Hibernate门槛较高。

● Hibernate优势:

Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。

Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象维护要方便。

Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。

Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。

7、Hibernate和JDBC优缺点对比?

● 相同点:

两者都是java数据库操作的中间件。

两者对数据库进行直接操作的对象都是线程不安全的,都需要及时关闭。

两者都可对数据库的更新操作进行显式的事务处理。

● 不同点:

JDBC是SUN公司提供一套操作数据库的规范,使用java代码操作数据库。Hibernate是一个基于jdbc的主流持久化框架,对JDBC访问数据库的代码做了封装。

使用的SQL语言不同:JDBC使用的是基于关系型数据库的标准SQL语言,Hibernate使用的是HQL(Hibernate query language)语言。

操作的对象不同:JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行,Hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中。

数据状态不同:JDBC操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致,而Hibernate操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的。

8、关于Hibernate的orm思想你了解多少?

ORM指的是对象关系型映射(Object RelationShip Mapping),指的就是我们通过创建实体类对象和数据库中的表关系进行一一对应,来实现通过操作实体类对象来更改数据库里边的数据信息。这里边起到关键作用的是通过Hibernate的映射文件+Hibernate的核心配置文件。

9、get和load的区别?

● get是立即加载,load是延时加载。

● get会先查一级缓存,再查二级缓存,然后查数据库;load会先查一级缓存,如果没有找到就创建代理对象,等需要的时候去查询二级缓存和数据库。(这里就体现load的延迟加载的特性。)

● get如果没有找到会返回null,load如果没有找到会抛出异常。

● 当我们使用session.load()方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的id值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出sql语句,从数据库中去查询我们的对象;相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来。

10、如何进行Hibernate的优化?

● 数据库设计调整。

● HQL优化。

● API的正确使用(如根据不同的业务类型选用不同的集合及查询API)。

● 主配置参数(日志,查询缓存,fetch_size,batch_size等)。

● 映射文件优化(ID生成策略,二级缓存,延迟加载,关联优化)。

● 一级缓存的管理。

● 针对二级缓存,还有许多特有的策略。

● 事务控制策略。

11、什么是Hibernate延迟加载?

延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。在Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在Hibernate3中还提供了对属性的延迟加载。

延迟加载的过程:通过代理(Proxy)机制来实现延迟加载。Hibernate从数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据(除标识符外),Hibernate并不从数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都为默认值;只有在真正需要使用该对象的数据时才创建这个真正的对象,真正从数据库中加载它的数据。

12、No Session问题原理及解决方法?

No session问题报错如下:

根据字面上的意思,是指代理不能被初始化,session已经关闭。

● No session问题产生的原因:

当执行Session的load()方法时,Hibernate不会立即执行查询所查询对象关联的对象(在此我们统称被关联的对象类为A类),仅仅返回A类的代理类的实例,这个代理类具由以下特征:

由Hibernate在运行时动态生成,它扩展了A类,因此它继承了A类的所有属性和方法,但它的实现对于应用程序是透明的。

当Hibernate创建A类代理类实例时,仅仅初始化了它的OID属性,其他属性都为null,因此这个代理类实例占用的内存很少。

当应用程序第一次访问A代理类实例时(例如调用a..getXXX()或a.setXXX()方法),Hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库中加载A对象的所有数据。但有个例外,那就是当应用程序访问A代理类实例的getId()方法时,Hibernate不会初始化代理类实例,因为在创建代理类实例时OID就存在了,不必到数据库中去查询。

Hibernate采用CGLIB工具来生成持久化类的代理类。CGLIB是一个功能强大的Java字节码生成工具,它能够在程序运行时动态生成扩展Java类或者实现Java接口的代理类。

Hibernate中如果采用load加载的话(默认的是延迟加载),也就是lazy=true操作,因此,当调用完load后,session即可关闭。又因为我们的session只是放置到了Dao层,表现层根本获取不到,所以在表现层调用的时候,session已经关闭,报错。

13、Spring的两种代理JDK和CGLIB的区别浅谈?

Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

● 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,或者强制使用CGLIB实现AOP。

● 如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。

14、叙述Session的缓存的作用?

● 减少访问数据库的频率。应用程序从内存中读取持久化对象的速度显然比到数据库中查询数据的速度快多了,因此Session的缓存可以提高数据访问的性能。

● 保证缓存中的对象与数据库中的相关记录保持同步。当缓存中持久化对象的状态发生了变换,Session并不会立即执行相关的SQL语句,这使得Session能够把几条相关的SQL语句合并为一条SQL语句,以便减少访问数据库的次数,从而提高应用程序的性能。

15、Session的清理和清空有什么区别?

Session清理缓存是指按照缓存中对象的状态的变化来同步更新数据库;清空是Session的关闭;

16、请简述Session的特点有哪些?

● 不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个Session实例。

● Session实例是轻量级的,所谓轻量级是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创建或销毁Session对象,例如为每个客户请求分配单独的Session实例,或者为每个工作单元分配单独的Session实例。

● 在Session中,每个数据库操作都是在一个事务(transaction)中进行的,这样就可以隔离开不同的操作(甚至包括只读操作)。

17、比较Hibernate三种检索策略的优缺点?

● 立即检索

● 优点:对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象;

● 缺点:1.select语句太多;2.可能会加载应用程序不需要访问的对象白白浪费许多内存空间;

● 延迟检索

● 优点:由应用程序决定需要加载哪些对象,可以避免可执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并且能节省内存空间;

● 缺点:应用程序如果希望访问游离状态代理类实例,必须保证他在持久化状态时已经被初始化;

● 迫切左外连接检索

●优点:

1、对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地冲一个对象导航到与它关联的对象。

2、使用了外连接,select语句数目少;

● 缺点:

1、可能会加载应用程序不需要访问的对象,白白浪费许多内存空间;

2、复杂的数据库表连接也会影响检索性能;