Hibernate常见面试题汇总

1.在数据库中条件查询速度很慢的时候,如何优化?

  1.建索引

  2.减少表之间的关联

  3.优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面

  4.简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据

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

  解决方案一,按照Object[]数据取出数据,然后自己组bean

  解决方案二,对每个表的bean写构造函数,比如表一要查出field1,field2两个字段,那么有一个构造函数就是Bean(type1 filed1,type2 field2) ,然后在hql里面就可以直接生成这个bean了。具体怎么用请看相关文档,我说的不是很清楚。

  session.load()session.get()的区别

  Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。其区别在于:

  如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException

  Load方法可返回实体的代理类实例,而get方法永远直接返回实体类。

  load方法可以充分利用内部缓存和二级缓存中的现有数据,而get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取。

  Session在加载实体对象时,将经过的过程:

  首先,Hibernate中维持了两级缓存。第一级缓存由Session实例维护,其中保持了Session当前所有关联实体的数据,也称为内部缓存。而第二级缓存则存在于SessionFactory层次,由当前所有由本SessionFactory构造的Session实例共享。出于性能考虑,避免无谓的数据库访问,Session在调用数据库查询功能之前,会先在缓存中进行查询。首先在第一级缓存中,通过实体类型和id进行查找,如果第一级缓存查找命中,且数据状态合法,则直接返回。之后,Session会在当前“NonExists”记录中进行查找,如果“NonExists”记录中存在同样的查询条件,则返回null“NonExists”记录了当前Session实例在之前所有查询操作中,未能查询到有效数据的查询条件(相当于一个查询黑名单列表)。如此一来,如果Session中一个无效的查询条件重复出现,即可迅速作出判断,从而获得最佳的性能表现。

  对于load方法而言,如果内部缓存中未发现有效数据,则查询第二级缓存,如果第二级缓存命中,则返回。

  如在缓存中未发现有效数据,则发起数据库查询操作(Select SQL),如经过查询未发现对应记录,则将此次查询的信息在“NonExists”中加以记录,并返回null

  根据映射配置和Select SQL得到的ResultSet,创建对应的数据对象。

  将其数据对象纳入当前Session实体管理容器(一级缓存)。

  执行Interceptor.onLoad方法(如果有对应的Interceptor)。

  将数据对象纳入二级缓存。

  如果数据对象实现了LifeCycle接口,则调用数据对象的onLoad方法。

  返回数据对象。

  Hibernate的主键生成机制

 

 另外由于常用的数据库,如OracleDB2SQLServerMySql 等,都提供了易用的主键生成机制(Auto-Increase 字段或者Sequence)。我们可以在数据库提供的主键生成机制上,采用generator-class=native的主键生成方式。

 

 

 不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,大量并发insert数据时可能会引起表之间的互锁。数据库提供的主键生成机制,往往是通过在一个内部表中保存当前主键状态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),之后每次插入数据会读取这个最大值,然后加上递增量作为新记录的主键,之后再把这个新的最大值更新回内部表中,这样,一次Insert操作可能导致数据库内部多次表读写操作,同时伴随的还有数据的加锁解锁操作,这对性能产生了较大影响。因此,对于并发Insert要求较高的系统,推荐采用uuid.hex 作为主键生成机制。

 

1Hibernate缓存概述

缓存是介于物理数据源与应用程序之间,是数据库数据在内存中的存放临时copy的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用的运行性能。Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做缓存命中"),则就直接把命中的数据作为结果加以利用,避免了建立数据库查询的性能损耗。

2Hibernate缓存分类

一级缓存(session):内部缓存

事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。

二级缓存(sessionFactory):缓存被应用范围内的所有事务共享。 这些事务有可能是并发访问缓存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时, 缓存也就结束了生命周期,二级缓存存在于应用范围。集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性, 缓存中的数据通常采用对象的松散数据形式,二级缓存也存在与应用范围。

注意:对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,再加上集群范围还有数据同步的问题,所以应当慎用。多种范围的缓存处理过程持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,还可以到应用范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询了。

缓存应用的范围:修改少,数量在可以接受的范围内

使用二级缓存的原则:

数据不会被第三方修改

同一数据系统经常引用

数据大小在可接受范围之内

关键数据或不会被并发更新的数据

hibernate引入第三方的缓存组件EHCACHE,下面是具体的实现步骤:

修改hibernate.cfg.xml配置引入ehCache缓存

1.            <hibernate-configuration> 

2.             

3.                                    <session-factory> 

4.             

5.                                            <property name="hibernate.cache.provider_class"> 

6.             

7.                                                    net.sf.ehcache.hibernate.EhCacheProvider  

8.             

9.                                            </< SPAN>property> 

10.         

11.                                         

12.         

13.                                        <property name="hibernate.cache.use_query_cache">true</< SPAN>property> 

14.         

15.                                </< SPAN>session-factory> 

16.         

17.                        </< SPAN>hibernate-configuration> 

18.         

src根目录下加入ehcache.xml文件,具体内容如下:

19.        <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> 

20.         

21.                        <defaultCache 

22.         

23.                                    maxElementsInMemory="10000" 

24.         

25.                                    eternal="false" 

26.         

27.                                    timeToIdleSeconds="120" 

28.         

29.                                    timeToLiveSeconds="120" 

30.         

31.                                    overflowToDisk="true" 

32.         

33.                                    /> 

34.         

35.                        </< SPAN>ehcache> 

36.         

在映射文件中指定缓存同步策略

37.        <class name="com.tenly.bean.Student"> 

38.         

39.                                <cache usage="read-write"> 

40.         

41.                                <set name="classroom"> 

42.         

43.                                        <cache usage="read-only"> 

44.         

45.                                </< SPAN>set> 

46.         

47.                        </< SPAN>class> 

48.         

usage属性说明:

◆read-only:只读。对于不会发生改变的数据,可使用只读型缓存。

◆nonstrict-read-write:不严格可读写缓存。如果应用程序对并发访问下的数据同步要求不是很严格的话,而且数据更新操作频率较低。采用本项,可获得良好的性能。

◆read-write 对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题.

◆transactional(事物型)在Hibernate中,事务型缓存必须运行在JTA事务环境中。在测试query时,说明其将用二级缓存

49.        query.setCacheable(true); 

3、释放缓存:

一级缓存的释放

Session.evict(XXX) 将某个特定的对象从内部缓存中清除,上述的XXX 为对象的实例名。使用此方法有两种适用情形,需要及时释放对象占用的内存维持系统的稳定性是不希望当前Session继续运用此对象的状态变化来同步更新数据库。Session.clear()清除所有的一级缓存

二级缓存的释放

SessionFacatoyr.evict(XXX) 将某个特定的对象从内部缓存中清除,上述的XXX 为对象的实例名。使用此方法有两种适用情形,需要及时释放对象占用的内存维持系统的稳定性是不希望当前Session继续运用此对象的状态变化来同步更新数据库。SessionFactory.clear()清除所有的二级缓存

4、查询缓存:

二级缓存策略的一般过程:

Hibernate进行条件查询的时候,总是发出一条select * from XXX where …XXX为 表名,类似的语句下文统称Select SQL)这样的SQL语句查询数据库,一次获得所有的符合条件的数据对象。把获得的所有数据对象根据ID放入到第二级缓存中。当Hibernate根据ID访问数据对象的时候,首先从内部缓存中查找,如果在内部缓存中查不到就配置二级缓存,从二级缓存中查;如果还查不到,再查询数据库,把结果按照ID放入到缓存。添加数据、删除、更新操作时,同时更新二级缓存。这就是Hibernate做批处理的时候效率不高的原因,原来是要维护二级缓存消耗大量时间的缘故。

条件查询的处理过程:

第一次查找age>20的所有学生信息,然后纳入二级缓存。第二次我们的查询条件变了,查找age>15的所有学生信息,显然第一次查询的结果完全满足第二次查询的条件,但并不是满足条件的全部数据。这样的话,我们就要再做一次查询得到全部数据才行。如果我们执行的是相同的条件语句,Hibernate引入Query Cache的。

查询缓存策略的一般过程:

完全相同的Select SQL重复执行。重复执行期间,Query Key对应的数据表不能有数据变动(比如添、删、改操作)

启用Query Cache,我们需要在hibernate.cfg.xml中进行配置,参考配置如下(只列出核心配置项):

50.        <hibernate-configuration> 

51.         

52.                                                <session-factory> 

53.         

54.                                                        <property name="hibernate.cache.user_query_cache">true</< SPAN>property> 

55.         

56.                                                </< SPAN>session-factory> 

57.         

58.                                        </< SPAN>hibernate-configuration> 

59.         

在查询执行之前,将Query.Cacheable设置为true,而且每次都应该这样。比如:

60.        Query query=session.createQuery(hql).setInteger(0.15);  

61.         

62.                                        query.setCacheable(true);  

63.         

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值