Hibernate面试题

一.简答题 1.请说出Hibernate中持久化对象的生命周期以及各种状态直接的区别,并描述相互之间是如何转换的。 Hibernate中持久化对象的生命周期有临时态、持久态和游离态三种。 处于临时态的对象主键值为空,并且未与session关联,数据未保存到数据库中 处于持久态的对象与session关联起来,持久化后对象中的数据被保存到数据库中,并且主键值按照.hbm.xml文件中配置的生成方式生成相应的值 处于游离态的对象脱离了session的管理,是持久化后的一种状态,主键值按照.hbm.xml文件中配置的生成方式生成相应的值 当new一个新的对象时,该对象处于临时态 当该对象被当作session的参数使用的时候,该对象处于持久态 事务提交,session关闭后,该对象处于游离态 2.hibernate与数据库连接的实现?并解释了一下,例如文件是通过流来实现的!hibernate与数据库连接是通过什么实现的? Hibernate与数据库的连接是通过JDBC实现的 3.spring和hibernate的事务管理方式有什么不同? hibernate的事务管理方式仅仅就是托管给JDBC(如果用JTA那么就是JTA),而JDBC的一切行为包括事务是基于一个connection的,那么hibernate委托给JDBC的事务也就是基于一个session。JTA与JDBC事务不同在于可以跨连接。 spring也是调用hibernate中事务管理的API。hibernate的事务管理,一般是编程性的。而委托给spring之后,可以使用声明式的,也就是可以在XML之中配置哪些需要进行事务管理 4.用hibernate的session时要注意几点 1.在更新数据时,要用open() 2.使用完之后,要close(),这样连接池会回收该连接。 5.说说在hibernate中使用Integer做映射和使用int做映射之间有什么差别 使用int做映射,hibernate会自动把int类型转换为Integer类型,以便统一以对象方式处理数据。使用Integer就无须转换。 在从数据库中取数据的时候,如果是用Integer做的映射,则要求PO对象中对应的类型也必须为Integer类型,使用的时候需要转换为int。如果是int型,则无须转换。 6.一个网站应用,请设计一个持久化类User,他可能有多张会员卡号、需要多个email地址(数量不定)作为其身份验证的方式 设计三个类。User类、会员卡类和email类。User类与会员卡类和email类之间是一对多的关系 7.请简单评价该设计的优劣:身份证号码作为一个person表的主键 一个表的主键值设计最好不要采用具有业务含义的字段。理由有二 (1).具有业务含义的字段的长度不固定 (2).具有业务含义的字段的取值范围不定。可能是纯数字,也可能是纯字符,或者是数字和字符的混合情况。 上述两个方面一但发生变动将不利于业务层的处理。 8.Hibernate如何获取指定主键id的某对象,请举例,并进行可能的优劣比较 三种方式:get(),load()和find() Get()和load()是先在缓存中查找对象,如果找不到再去数据库中查询; Find()是无论何时都在数据库中查询对象。 三者比较起来Get()和load()的性能稍好一点。 二.问答题 1.请说出Hibernate中的映射关系有几种,分别是什么,如何配置 Hibernate中的映射关系有一对一、一对多、多对多三种。 一对一关系比较简单,只需在主控方(由谁想得到谁,前者即是主控方)定义。配置如下: 简单模式: 完整模式: 一对多关系分为单向一对多关系和双向一对多关系。 单向一对多关系只需在“一”方进行配置,双向一对多需要在关联双方均加以配置。配置如下: 单向一对多: 双向一对多: 一的一方: 多的一方: 被动方的记录由Hibernate负责读取,之后存放在主控方指定的Collection类型属性中。 多对多关联:由于多对多关联的性能不佳,在设计中应避免大量使用。应根据情况,采取延迟加载机制来避免无谓的性能开销。配置如下: 2.请描述对象建模时的继承关系在Hibernate中有几种映射方式,如何映射 一共有三种: 每颗类继承树使用一张表,配置如下: 三个类对应的字段都在一个数据表里表示。subtype字段标识存储的是哪个子类,与xml文件中的 对应。 每个子类各一张表,配置如下: 每个具体类各一张表,配置如下: 3.请描述Hibernate中的缓存机制 缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。 缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期。 Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分为两类:内置缓存和外置缓存。Session的缓存是内置的,不能被卸载,也被称为Hibernate的第一级缓存。Session的缓存是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来,SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。 Hibernate的这两级缓存都位于持久化层,存放的都是数据库数据的拷贝,那么它们之间的区别是什么呢?为了理解二者的区别,需要深入理解持久化层的缓存的两个特性:缓存的范围和缓存的并发访问策略。 持久化层的缓存的范围 缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。 1 事务范围:缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的的对象形式。 2 进程范围:缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期,进程结束时,缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据,所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据,但是对象分解为松散的算法比对象序列化的算法要求更快。 3 集群范围:在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式。 对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,因为访问的速度不一定会比直接访问数据库数据的速度快多少。 持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,还可以到进程范围或集群范围的缓存内查询,如果还是没有查到,那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存,通常它是必需的;进程范围或集群范围的缓存是持久化层的第二级缓存,通常是可选的。 持久化层的缓存的并发访问策略 当多个并发的事务同时访问持久化层的缓存的相同数据时,会引起并发问题,必须采用必要的事务隔离措施。 在进程范围或集群范围的缓存,即第二级缓存,会出现并发问题。因此可以设定以下四种类型的并发访问策略,每一种策略对应一种事务隔离级别。 事务型:仅仅在受管理环境中适用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。 读写型:提供了Read Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读这类的并发问题。 非严格读写型:不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须为该数据配置一个很短的数据过期时间,从而尽量避免脏读。对于极少被修改,并且允许偶尔脏读的数据,可以采用这种并发访问策略。 只读型:对于从来不会修改的数据,如参考数据,可以使用这种并发访问策略。 事务型并发访问策略是事务隔离级别最高,只读型的隔离级别最低。事务隔离级别越高,并发性能就越低。 什么样的数据适合存放到第二级缓存中? 1、很少被修改的数据 2、不是很重要的数据,允许出现偶尔并发的数据 3、不会被并发访问的数据 4、参考数据 不适合存放到第二级缓存的数据? 1、经常被修改的数据 2、财务数据,绝对不允许出现并发 3、与其他应用共享的数据。 Hibernate的二级缓存 如前所述,Hibernate提供了两级缓存,第一级是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。第一级缓存是必需的,不允许而且事实上也无法卸除。在第一级缓存中,持久化类的每个实例都具有唯一的OID。 第二级缓存是一个可插拔的的缓存插件,它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的,可以在每个类或每个集合的粒度上配置第二级缓存。 Hibernate的二级缓存策略的一般过程如下: 1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。 2) 把获得的所有数据对象根据ID放入到第二级缓存中。 3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。 4) 删除、更新、增加数据的时候,同时更新缓存。 Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query缓存。 Hibernate的Query缓存策略的过程如下: 1) Hibernate首先根据这些信息组成一个Query Key,Query Key包括条件查询的请求一般信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows),等。 2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果列表根据Query Key放入到Query缓存中。 3) Query Key中的SQL涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的Query Key都要从缓存中清空。

版权声明:本文为博主原创文章,未经博主允许不得转载。

你可能感兴趣的:(数据库,Hibernate,面试,session,Integer,query)