hibenate的面试总结:
可能现在大家常常还会遇到一个些面试的时候问一些关于hibernate的问题,我个人觉得,这些东西一般做过开发的人在使用上没有任何的问题的,但是如果是要你来说就不一定能够说好的,下面是从goole上找的一些常见的面试。
1.Hibernate session接口的get和load方法有何异同?
答: 其实它们也没有什么不同的, 作用其实都是一样的,但是有一定的区别,get是每次都会从数据库取数据以保证数据的可靠性,而load会返回proxy,相当于是一个存根,它的值会去hibernate中的session的二级缓存里去找,如果找不到目则会laxy load一下,简单来说,用get的时候,当为空的时候不会抛出异常,反之load会抛.
2.在持久化层,对象分为哪些状态?分别列出来.
答:瞬时态(Transient)、持久态(Persistent)、脱管态(Detached)。
瞬时态(Transient)
是对象是创建时,瞬时对象在内存孤立存在,它是携带信息的载体,不和数据库的数据有任何关联关系,在Hibernate中,可通过session的save()或 saveOrUpdate()方法将瞬时对象与数据库相关联,并将数据对应的插入数据库中,此时该瞬时对象转变成持久化对象。
持久态(Persistent)
是该对象在数据库中已有对应的记录,并拥有一个持久化标识,如果是用hibernate的delete()方法,对应的持久对象就变成瞬时对象,因数据库中的对应数据已被删除,该对象不再与数据库的记录关联。
当一个session执行close()或clear()、evict()之后,持久对象变成脱管对象,此时持久对象会变成脱管对象,此时该对象虽然具有数据库识别值,但它已不在hibernate持久层的管理之下。
持久对象具有如下特点:
1. 和session实例关联;
2. 在数据库中有与之关联的记录。
脱管态(Detached)
当与某持久对象关联的session被关闭后,该持久对象转变为脱管对象。当脱管对象被重新关联 到session上时,并再次转变成持久对象。
脱管对象拥有数据库的识别值,可通过update()、saveOrUpdate()等方法,转变成持久对象。
脱管对象具有如下特点:
1.本质上与瞬时对象相同,在没有任何变量引用它时,JVM会在适当的时候将它回收;
2. 比瞬时对象多了一个数据库记录标识值。
3.lock和update区别
答: update是把一个已经更改过的脱管状态的对象变成持久状态
lock是把一个没有更改过的脱管状态的对象变成持久状态(针对的是因Session的关闭 而处于脱管状态 的po对象(2),不能针对因delete而处于脱管状态的po对象)
对应更改一个记录的内容,两个的操作不同:
update的操作步骤是:
(1)属性改动后的脱管的对象的修改->调用update
lock的操作步骤是:
(2)调用lock把未修改的对象从脱管状态变成持久状态-->更改持久状态的对象的内容-->等待flush或 者手动flush
4.save 和update区别
答: save是把一个对象做为一个新的数据保存, update则是把一个脱管状态的对象或自由态对象(一 定要和一个记录对应)更新到数据库,其实一个是保存一个是更新,一看都知道是有什么区别了。
5.update 和saveOrUpdate区别
答:这个是比较好理解的,顾名思义,saveOrUpdate基本上就是合成了save和update,而update只是update;引用hibernate reference中的一段话来解释他们的使用场合和区别。通常下面的场景会使update()saveOrUpdate():
程序在第一个session中加载对象,接着把session关闭
该对象被传递到表现层
对象发生了一些改动
该对象被返回到业务逻辑层最终到持久层
程序创建第二session调用第二个session的update()方法持久这些改动
saveOrUpdate(po)做下面的事:
如果该po对象已经在本session中持久化了,在本session中执行saveOrUpdate不做任何事
如果savaOrUpdate(新po)与另一个与本session关联的po对象拥有相同的持久化标识(identifier),抛出一个异常
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [org.itfuture.www.po.Xtyhb#5]
saveOrUpdate如果对象没有持久化标识(identifier)属性,对其调用save() ,否则update() 这个对 象
6.flush和update区别
答:这两个的区别好理解update操作的是在自由态或脱管状态(因session的关闭而处于脱管状态)的对 象//updateSQL
而flush是操作的在持久状态的对象。
默认情况下,一个持久状态的对象的改动(包含set容器)是不需要update的,只要你更改了对象的 值,等待hibernate flush就自动更新或保存到数据库了。hibernate flush发生在以下几种情况中:
1, 调用某些查询的和手动flush(),session的关闭、SessionFactory关闭结合
get()一个对象,把对象的属性进行改变,把资源关闭。
2,transaction commit的时候(包含了flush)
7.在数据库中条件查询速度很慢的时候,如何优化?
a.建索引
b.减少表之间的关联
c.优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面
d.简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据
8.在Hibernate中进行多表查询,每个表中各取几个字段,也就是说查询出来的结果集并没有一个实体类与之对应,如何解决这个问题?
解决方案一,按照t数据取出数据,然后自己组bean
解决方案二,对每个表的bean写构造函数,比如表一要查出field1,field2两个字段,那么有一个构造函数就是Bean(type1filed1,type2field2),然后在hql里面就可以直接生成这个bean了。
9.Hibernate的主键生成机制
a.assigned 主键由外部程序负责生成,无需Hibernate参与。
b.hilo 通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。
c.seqhilo 与hilo类似,通过hi/lo算法实现的主键生成机制,只是主键历史状态保存在Sequence中,适用于 支持Sequence的数据库,如Oracle。
d.increment 主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大 值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:如果当前有 多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主 键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。
e.identity 采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL中的主键生成机制。
f.sequence 采用数据库提供的sequence 机制生成主键。如Oralce 中的Sequence。
g.native 由Hibernate根据底层数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方 式。
h.uuid.hex 由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)作 为主键。
i.uuid.string 与uuid.hex 类似,只是生成的主键未进行编码(长度16)。在某些数据库中可能出现问题(如 PostgreSQL)。
j.foreign 使用外部表的字段作为主键。一般而言,利用uuid.hex方式生成主键将提供最好的性能和数据库 平台适应性。
这10中生成OID标识符的方法,increment比较常用,把标识符生成的权力交给Hibernate处理.但是当同时多个Hibernate应用操作同一个数据库,甚至同一张表的时候.就推荐使用identity依赖底层数据库实现,但是数据库必须支持自动增长,当然针对不同的数据库选择不同的方法.如果你不能确定你使用的数据库具体支持什么的情况下.可以选择用native让Hibernate来帮选择identity,sequence,或hilo. 另外由于常用的数据库,如Oracle、DB2、SQLServer、MySql等,都提供了易用的主键生成机制(Auto-Increase字段或者Sequence)。我们可以在数据库提供的主键生成机制上,采用generator-class=native的主键生成方式。
不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,大量并发insert数据时可能会引起表之间的互锁。数据库提供的主键生成机制,往往是通过在一个内部表中保存当前主键状态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),之后每次插入数据会读取这个最大值,然后加上递增量作为新记录的主键,之后再把这个新的最大值更新回内部表中,这样,一次Insert操作可能导致数据库内部多次表读写操作,同时伴随的还有数据的加锁解锁操作,这对性能产生了较大影响。因此,对于并发Insert要求较高的系统,推荐采用uuid.hex作为主键生成机制。
10.Hibernate的检索方式
a.导航对象图检索
b.OID检索
c.HQL检索
d.QBC检索
e.本地SQL检索
11. Forward与Global-Forward的区别
Forward是根据Action return的值找到对应的JSP页。当多个Action共同return同一个值时,可将这个Forward元 素写在Global-Forward中。
12.在Hibernate应用中Java对象的状态有哪些?
1.临时状态(transient):刚刚用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态
Java对象被称为临时对象。
2.持久化状态(persistent):已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久 化对象。
3.游离状态(detached):已经被持久化,但不再处于Session的缓存中。处于游离状态的Java对象被称为游离对 象。
13.三种检索策略是什么,分别适用于哪种场合?
立即检索-- 优点:对应用程序完全透明,缺点:select语句数目多。适用:类级别。
延迟检索-- 优点: 由应用程序决定加载哪些对象,可以避免执行多余的select语句以及避免加载不需要访问的对象, 节省内存空间,提高检索效率。 缺点: 应用程序如果要访问游离态的代理类实例,必须保证 它在持久化时已经被初始化。 适用: 一对多或多对多关联。应用程序不需要立即访问或者根 本不会访问的对象。
迫切左外连接检索: 优点:对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以方便的从 一个对象导航到另一个与它相关联的对象。使用了外连接,select语句数目少。 缺点:可能 会加载程序不许要访问的对象。复杂的数据库表连接形象检索性能。 适用:一对一或多对一 关联。应用程序需要立即访问的对象。数据库系统具有良好的表连接性能。
14.ORM解决的不匹配问题(域模型与关系模型之间存在的不匹配)
a.域模型是面向对象的,关系模型是面向关系的。
b.域模型中有继承关系,关系模型中不能直接表示继承关系。
c.域模型中有多对多关联关系,关系模型中通过连接表来表示多对多关联关系。
d.域模型中有双向关联关系,关系模型中只有单向参照关系,而且总是many参照one方。
e.域模型提倡精粒度模型,关系模型提倡粗粒度模型。
15.映射继承关系的三种方式?
a.继承关系树的每个具体类对应一张表:在具体类对应的表中,不仅包含和具体类属性对应的字段,还包括与具 体类的父类属性对应的字段。
b.继承关系树的根类对应一张表:在根类对应的表中,不仅包括根类属性对应的字段, 还包括根类的所有子类属 性对应的字段。
c.继承关系树中的每个类对应一张表,每个表中只包括和这个类本身属性对应的字段,子类的表参照父类对应的 表。
16.Session的find()方法以及Query接口的区别。
Session类的find()方法以及Query接口都支持HQL检索方式。这两者的区别在于,前者只是执行一些简单HQL查询语句的便捷方法,它不具有动态绑定参数的功能,而且在Hibernate3.x版本中,已经淘汰了find()方法;而Query接口才是真正的HQL查询接口,它提供了以上列出的各种查询功能。
17.hibernate的配置文件(hibernate.properties)中 hibernate.show_sql=true/flase
在开发阶和测试段应设置为()在发布阶段应设置为();true\false
18.list要的实现类有那些? 并按照存储结构、机制简单的说一下。
LinkedList、ArryList、Vector。 LinkedList 采用链表数据结构、ArryList代表大小可变的数组。 Vector与ArryList功能比较相似,区别在于Vector采用同步、ArryList没有采用。
19.继承的三种方式
a.继承关系树的每个具体类对应一张表:在具体类对应的表中,不仅包含和具体类属性对应的字段,还包括与具 体类的父类属性对应的字段。
b.继承关系树的根类对应一张表:在根类对应的表中,不仅包括根类属性对应的字段,还包括根类的所有子类属 性对应的字段。
c.继承关系树中的每个类对应一张表,每个表中只包括和这个类本身属性对应的字段,子类的表参照父类对应的 表。
20.Session接口是Hibernate应用使用最广泛的接口。Session也被称为持久化管理器,它提供了和持久化相关的操作,如添加、更新、删除、加载和查询对象。
21.请简述Session的特点有哪些?
a.不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个Session实例。
b.Session实例是轻量级的,所谓轻量级是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创 建或销毁Session对象,例如为每个客户请求分配单独的Session实例,或者为每个工作单元分配单独的 Session实例。
c.在Session 中,每个数据库操作都是在一个事务(transaction)中进行的,这样就可以隔离开不同的操作(甚至包 括只读操作)。
22.Hibernate中采用XML文件来配置对象-关系映射的优点有那些?
Hibernate既不会渗透到上层域模型中,也不会渗透到下层数据模型中。软件开发人员可以独立设计域模型,不必强迫遵守任何规范。数据库设计人员可以独立设计数据模型,不必强迫遵守任何规范。对象-关系映射不依赖于任何程序代码,如果需要修改对象-关系映射,只需修改XML文件,不需要修改任何程序,提高了软件的灵活性,并且使维护更加方便。
23. 叙述Session的缓存的作用
a.减少访问数据库的频率。应用程序从内存中读取持久化对象的速度显然比到数据库中查询数据的速度快多了, 因此Session的缓存可以提高数据访问的性能。
b.保证缓存中的对象与数据库中的相关记录保持同步。当缓存中持久化对象的状态发生了变换,Session并不会 立即执行相关的SQL语句,这使得Session能够把几条相关的SQL语句合并为一条SQL语句,以便减少访问数 据库的次数,从而提高应用程序的性能。
24.多个事务并发运行时的并发问题有哪些?
第一类丢失更新;脏读;虚读;不可重复读;第二类丢失更新;
25.ORM解决的不匹配问题(域模型与关系模型之间存在的不匹配)
域模型是面向对象的,关系模型是面向关系的。域模型中有继承关系,关系模型中不能直接表示继承关系。域模型中有多对多关联关系,关系模型中通过连接表来表示多对多关联关系。域模型中有双向关联关系,关系模型中只有单向参照关系,而且总是many参照one方。域模型提倡精粒度模型,关系模型提倡粗粒度模型。
26.session的清理和清空有什么区别?
session清理缓存是指按照缓存中对象的状态的变化来同步更新数据库;清空是session关闭;
27.Hibernate工作原理及为什么要用?
原理: 1.读取并解析配置文件
2.读取并解析映射信息,创建SessionFactory
3.打开Sesssion
4.创建事务Transation
5.持久化操作
6.提交事务
7.关闭Session
8.关闭SesstionFactory
为什么要用:
1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码 工作
3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对 一到多对多的各种复杂关系。
28.Hibernate是如何延迟加载?
1. Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)
2. Hibernate3 提供了属性的延迟加载功能 当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
29.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many
30.说下Hibernate的缓存机制
1. 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存
2. 二级缓存: a) 应用及缓存 b) 分布式缓存 条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率 低、同一数据被系统频繁使用、非 关键数据 c) 第三方缓存的实现
31.Hibernate的查询方式
1、 属性查询 2、 参数查询、命名参数查询 3、 关联查询 4、 分页查询 5、 统计函数