Hibernate面试题集锦(附解析)

一,选择题:
(1)一般情况下,关系数据模型与对象模型之间有哪些匹配关系(多选)
A)表对应类B)记录对应对象C)表的字段对应类的属性D)表之间的参考关系对应类之间的依赖关系
解析:
答案:abc
a.表必须对应类(可以名字不一样,但不提倡那么干)
b......
c.要是查询出来的数据为我们所用,并且得到好的封装
d.在做many-to-many对应关系是就算没有外键关系与之对应,也也可以操作
 
(2)以下关于SessionFactory的说法哪些正确?(多选)
A)对于每个数据库事务,应该创建一个SessionFactory对象
B)一个SessionFactory对象对应一个数据库存储源。
C)SessionFactory是重量级的对象,不应该随意创建。如果系统中只有一个数据库存储源,只需要创建一个。
D)SessionFactory的load()方法用于加载持久化对象
解析:
答案:bc
sessionFactory是一个重量级的对象,因此创建是会耗费大量资源。一个SessionFactory对应一个数据库存储源。
 
(3)Customer类中有一个Set类型的orders属性,用来存放Order订单对象,在Customer.hbm.xml文件中,用哪个元素映射orders属性?  

A)<set> B)<one-to-many> C)<many-to-one> D)<property>
解析:
答案:a
学过hibernate的都知道
(4)元素有一个cascade属性,如果希望Hibernate级联保存集合中的对象,casecade属性应该取什么值?(单选)
A)noneB)saveC)deleteD)save-update
解析:
答案:d

cascade属性值描述
none在保存、更新或者删除对象时,忽略其他关联的对象,它是级联的默认值
save-update当通过Session的Save()、Update()以及SaveOrUpdate()方法来保存、更新对象时,级联保存关联的临时对象,并更新关联的游离对象。
delete当通过Session的Delete()方法删除当前对象时,同时会删除关联的所有对象。
all包含save-update以及delete的行为,此外对当前对象进行Evict()或者Lock()方法时会对关联的对象进行同样的操作。
delete-orphan删除所有和当前对象解除关联关系的对象。
all-delete-orphan包含all和delete-orphan的行为。
 
(5)以下哪些属于Session的方法?
A)load()B)save()C)delete()D)update()E)open()F)close()
解析:
答案:ABCDF
 
(6)以下程序的打印结果是什么?(单选)
 
tx = session.beginTransaction();  
Customer c1=(Customer)session.load(Customer.class,new Long(1));  
Customer c2=(Customer)session.load(Customer.class,new Long(1));  
System.out.println(c1==c2);  
tx.commit();  
session.close();
A)运行出错,抛出异常B)打印falseC)打印true
解析:
答案:C
==比较的是两个基本数据类型变量的值和应用类型的地址
equals比较的是两个对象是否是同一对象的应用
 
 
(7)以下程序代码对Customer的name属性修改了两次:
tx = session.beginTransaction();  
Customer customer=(Customer)session.load(Customer.class,  
new Long(1));  
customer.setName(\"Jack\");  
customer.setName(\"Mike\");  
tx.commit();
执行以上程序,Hibernate需要向数据库提交几条update语句?(单选)
A)0 B)1 C)2 D)3
解析:
答案:B
 
(8)在持久化层,对象分为哪些状态?(多选)
A)临时状态B)独立状态C)游离状态D)持久化状态
解析:
答案:ACD
在Hibernate中,对象有三种状态:临时状态、持久状态和游离状态。

临时状态: 当new一个实体对象后,这个对象处于临时状态 ,即这个对象只是一个保存临时数据的内存区域,如果没有变量引用这个对象,则会被jre垃圾回收机制回收。这个对象所保存的数据与数据库没有任何关系,除非通过Session的save或者SaveOrUpdate把临时对象与数据库关联,并把数据插入或者更新到数据库,这个对象才转换为持久对象。
例如:Emp e=new Emp();    //创建临时对象
          e.setEmpno((long) 8888);
          e.setEName("mike");
          ...
          EmpDAO d=new EmpDAO();
          d.save(e);      //持久化
          ...

持久状态:持久化对象的实例在数据库中有对应的记录,并拥有一个持久化表示(ID)。对持久化对象进行delete操作后,数据库中对应的记录将被删除,那么持久化对象与数据库记录不再存在对应关系,持久化对象变成临时状态。
    持久化对象被修改变更后,不会马上同步到数据库,知道数据库事务提交。在同步之前,持久化对象是脏的(Dirty)。
例如:
          Emp e=new Emp(); //创建了临时的对象
          EmpDAO edao= new empDAO();
          e=edao.findbyEmpno((long) 7786);    //使对象与数据库记录对应,从而持久化
          e.setEname("新的名字");                     //修改了持久化对象,使之处于 Dirty
          ......
          edao.saveorupdate(e);                      //保存,但是仍然 Dirty
          tran.commit();                                     //提交,实现与数据库同步,不再Dirty
          ......

游离状态:当Session进行了Close、Clear或者evict后,持久化对象虽然拥有持久化标识符和与数据库对应记录一致的值,但是因为会话已经消失,对象不在持久化管理之内,所以处于游离状态(也叫:脱管状态)。游离状态的对象与临时状态对象是十分相似的,只是它还含有持久化标识。

其中,持久化状态的对象,简称为:PO
而临时状态和游离状态的对象,简称为: VO

 
(9)对于以下程序,Customer对象在第几行变为持久化状态?(单选)
Customer customer=new Customer(); //line1  
customer.setName(\"Tom\"); //line2  
Session session1=sessionFactory.openSession(); //line3  
Transaction tx1 = session1.beginTransaction(); //line4  
session1.save(customer); //line4  
tx1.commit(); //line5  
session1.close(); //line6
A) line1 B)line2 C)line3 D)line4 E)line5 F)line6
解析:
答案:D
原因同8题所述
 
 
(10)对于以下程序,Customer对象在第几行变为游离状态?(单选)
Customer customer=new Customer(); //line1  
customer.setName(\"Tom\"); //line2  
Session session1=sessionFactory.openSession(); //line3  
Transaction tx1 = session1.beginTransaction(); //line4  
session1.save(customer); //line4  
tx1.commit(); //line5  
session1.close(); //line6
A) line1 B)line2 C)line3 D)line4 E)line5 F)line6
解析:
答案:F
原因同8题
 
(11)以下哪一种检索策略利用了外连结查询?(单选)
A)立即检索 B)延迟检索 C)迫切左外连结检索
解析:
答案:C
1、立即检索:
优点:
对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地从一个对象导航到与它关联的对象。
缺点:
[1]select语句数目多
[2]可能会加载应用程序不需要访问的对象,浪费时间和内存空间
优先考虑使用的场合:
[1]类级别
[2]应用程序需要立即访问的对象
[3]使用了二级缓存
2、延迟检索:
优点:
由应用程序决定需要加载哪些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并且节省内存空间
缺点:
应用程序如果需要访问游离状态的代理类实例,必须保证它在持久化状态时已经被初始化。
优先考虑使用的场合:
[1]一对多或者多对多关联
[2]应用程序不需要立即访问或者根本不访问的对象
3、迫切左外连接检索:
优点:
[1]对应用程序完全透明,不管对象处于之久化状态还是游离状态,应用程序都可以方便的从一个对象 导航到另一个与它关联的对象 。
[2]使用了外连接, select语句数目少(使用连接查询)
缺点:
[1]可能会加载应用程序不需要访问的对象,浪费内存空间
[2]复杂的数据表连接会影响检索性能
优先考虑使用的场合:
[1]多对一或者一对一关联
[2]应用程序需要立即访问的对象
[3]数据库系统具有良好的表连接性能
(12)假设对Customer类的orders集合采用延迟检索策略,编译或运行以下程序,会出现什么情况(单选)
Session session=sessionFactory.openSession();  
tx = session.beginTransaction();  
Customer customer=(Customer)session.get(Customer.class,new Long(1));  
tx.commit();  
session.close();  
Iterator orderIterator=customer.getOrders().iterator();
A)编译出错 B)编译通过,并正常运行 C)编译通过,但运行时抛出异常
解析:
答案:C
(13)关于HQL与SQL,以下哪些说法正确?(多选)
A)HQL与SQL没什么差别B)HQL面向对象,而SQL操纵关系数据库C)在HQL与SQL中,都包含select,insert,update,delete语句D)HQL仅用于查询数据,不支持insert,update和delete语句
解析:
答案:BD
HQL(Hibernate QUERY LANGUAGE)只能查询语句
 
 
 
(14)事务隔离级别是由谁实现的?(单选)
A)Java应用程序 B)Hibernate C)数据库系统 D)JDBC驱动程序
解析:
答案:C
地球人都知道
(15)悲观锁与乐观锁,哪个具有较好的并发性能?(单选)
A)悲观锁 B)乐观锁
解析:
答案:B
1.悲观锁

它指的是对数据被外界修改持保守态度。假定任何时刻存取数据时,都可能有另一个客户也正在存取同一笔数据,为了保持数据被操作的一致性,于是对数据采取了数据库层次的锁定状态,依靠数据库提供的锁机制来实现。  
基于jdbc实现的数据库加锁如下:  
select * from account where name="Erica" for update

在更新的过程中,数据库处于加锁状态,任何其他的针对本条数据的操作都将被延迟。本次事务提交后解锁。  
而hibernate悲观锁的具体实现如下:  
String sql="查询语句";  
Query query=session.createQuery(sql);  
query.setLockMode("对象",LockModel.UPGRADE);

说到这里,就提到了hibernate的加锁模式:

LockMode.NONE:无锁机制。  
LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动获取。  
LockMode.READ:Hibernate在读取记录的时候会自动获取。

这三种加锁模式是供hibernate内部使用的,与数据库加锁无关:

LockMode.UPGRADE:利用数据库的for update字句加锁。

在这里我们要注意的是:只有在查询开始之前(也就是hiernate生成sql语句之前)加锁,才会真正通过数据库的锁机制加锁处理。否则,数据已经通过不包含for updata子句的sql语句加载进来,所谓的数据库加锁也就无从谈起。  
但是,从系统的性能上来考虑,对于单机或小系统而言,这并不成问题,然而如果是在网络上的系统,同时间会有许多联机,假设有数以百计或上千甚至更多的并发访问出现,我们该怎么办?如果等到数据库解锁我们再进行下面的操作,我们浪费的资源是多少?--这也就导致了乐观锁的产生。

2.乐观锁

乐观锁定(optimistic locking)则乐观的认为资料的存取很少发生同时存取的问题,因而不作数据库层次上的锁定,为了维护正确的数据,乐观锁定采用应用程序上的逻辑实现版本控制的方法。

例如若有两个客户端,A客户先读取了账户余额100元,之后B客户也读取了账户余额100元的数据,A客户提取了50元,对数据库作了变更,此时数据库中的余额为50元,B客户也要提取30元,根据其所取得的资料,100-30将为70余额,若此时再对数据库进行变更,最后的余额就会不正确。

在不实行悲观锁定策略的情况下,数据不一致的情况一但发生,有几个解决的方法,一种是先更新为主,一种是后更新的为主,比较复杂的就是检查发生变动的数据来实现,或是检查所有属性来实现乐观锁定。

Hibernate 中透过版本号检查来实现后更新为主,这也是Hibernate所推荐的方式,在数据库中加入一个VERSON栏记录,在读取数据时连同版本号一同读取,并在更新数据时递增版本号,然后比对版本号与数据库中的版本号,如果大于数据库中的版本号则予以更新,否则就回报错误。

以刚才的例子,A客户读取账户余额1000元,并连带读取版本号为5的话,B客户此时也读取账号余额1000元,版本号也为5,A客户在领款后账户余额为500,此时将版本号加1,版本号目前为6,而数据库中版本号为5,所以予以更新,更新数据库后,数据库此时余额为500,版本号为6,B客户领款后要变更数据库,其版本号为5,但是数据库的版本号为6,此时不予更新,B客户数据重新读取数据库中新的数据并重新进行业务流程才变更数据库。

以Hibernate实现版本号控制锁定的话,我们的对象中增加一个version属性,例如:  
view plaincopy to clipboardprint?
public class Account {     
private int version;     
....     
public void setVersion(int version) {     
this.version = version;     
}     
public int getVersion() {     
return version;     
}     
....     
}    
public class Account {  
private int version;  
....  
public void setVersion(int version) {  
this.version = version;  
}  
public int getVersion() {  
return version;  
}  
....  
}

二,简答题

 1.Hibernate工作原理及为什么要用?

答:

原理:

1)读取并解析配置文件

2)读取并解析映射信息,通过SessionFactory创建Session

3)打开Sesssion

4)创建事务Transation

5)持久化操作

6)提交事务

7)关闭Session

为什么要用:

1) 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。

2) Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作

3)hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。

4)hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。



2. Hibernate是如何延迟加载?
答:

1) Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)

2)Hibernate3 提供了属性的延迟加载功能

当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
 

 

3.hibernate 进行多表查询每个表中各取几个字段,也就是说查询出来的结果集没有一个实体类与之对应如何解决?

 

可以将查询返回一个DynaBean比如

List<DynaBean>list=statement.executeSQLQuery("select a.aa,b.bb from a,b");

for(DynaBean db:list){

          String a1= (String)db.get("aa");

          Stringb1= (String)db.get("bb");

}

Or

List list=query.list();

Iterator it=list.itreator();

While(it.hasNext()){

        Object[]obj=(Object[])it.next();

        Stringal=(String)obj[0];

}

 

4.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)

答:类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many

 
 

5. 说下Hibernate的缓存机制

答:

hibernate中存在两种缓存,即内置缓存和外只缓存。

1) 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存

2) 二级缓存:

a) 应用及缓存

b) 分布式缓存

条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非 关键数据

c) 第三方缓存的实现
 

 

 

6. Hibernate的查询方式

Sql、Criteria,object comptosition

Hql:

1) 属性查询

2) 参数查询、命名参数查询

3) 关联查询

4) 分页查询

5) 统计函数

7.hibernate 中的 update() 和 saveOrUpdate() 的区别, session 的 load() 和 get() 的区别。

答:

 

Update 更新的是已有的数据,如果没有则会报错。 SaveOrUpdate 则可以将数据库中没有数据进行保存,有的数据进行修改

Load 和 get 都是查询数据对象。 Load 首先会从缓存中加载,如果缓存中没有该数据,则去数据库中查找, get 会直接去数据库加载。当数据的查询波动比较小时,可以使用 load 来优化数据操作,反之则会带来更大的负担

从这个可以将一些关于iterate和list()来优化考官对自己的认可之类的

 

 

8.Session清理缓存的三种模式
清理缓存的模式           

 Session查询方法                 

 Session的Commit方法                 

 Session的Flush方法   

           
9. Hibernate的主键生成机制
答:

在项目中,通常使用UUID(Universally Unique Identifier 唯一标示符)作为主键.

常用的组建有:

 

1) Assigned

     主键由外部程序负责生成,无需Hibernate参与。

2) hilo
     通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。
3) native       由Hibernate根据底层数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式。
4) increment

     主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。
  这种方式可能产生的问题是:如果当前有多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。

5) identity
      采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL中的主键生成机制。

6) sequence
      采用数据库提供的sequence 机制生成主键。如Oralce 中的Sequence。

你可能感兴趣的:(Hibernate面试题集锦(附解析))