Hibernate常用面试题

一)什么是Hibernate

Hibernate是一种用于Java环境的对象/关系映射解决方案。术语“对象/关系映射”是指将数据从对象模型表示映射到关系数据模型表示的技术(反之亦然)。

 

二)Hibernate优势

1、对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
2、Hibernate是一个基于JDBC的主流持久层框架,基于ORM实现。很大程度的简化DAO层编码工作。
3、hibernate使用java反射机制。
4、hibernate是轻量级框架,性能优秀,支持各种关系数据库,易于测试。

 

三)Hibernate工作原理
1、解析hibernate.cfg.xml配置文件
通过Configuration config = new Configuration().configure();
读取并解析hiberante.cfg.xml配置文件
2、读取并解析映射信息
hibernate.cfg.xml中的<mapping resource="com/User.hbm.xml"/>映射文件
3、创建SessionFactory对象
SessionFactory sf = config.buildSessionFactory();
4、打开Session
Session session = sf.openSession();
5、创建并启动事务
Transaction tx = session.beginTransaction();
6、CRUD持久化操作,增删改查
7、提交事务
tx.commit();
8、关闭session
9、关闭SessionFactory

 

四)Hibernate对象状态

1、瞬时状态:刚用new语句创建,尚未持久化,没有被session所关联,数据库中也没有该对象的记录。

2、持久化状态:数据被实例化,提交了事务,数据已经插入到数据库中。

3、游离状态:数据持久化,并关闭了Session,对象变为游离状态。

 

五)Hibernate几种数据查询方式

1、Hibernate Query Language(HQL)和Java Persistence Query Language(JPQL)都是面向对象模型的查询语言,其本质类似于SQL。JPQL是HQL的一个受很大启发的子集。JPQL查询始终是有效的HQL查询,但是反之则不成立。

HQL和JPQL都是执行查询操作的非类型安全方式。

2、标准Criteria查询是一种完全面向对象查询,是一种类型安全的查询方式。

3、原生SQL查询

 

六)如何优化Hibernate查询

1、使用双向一对多关联,不使用单向一对多

2、灵活使用单向一对多关联

3、不用一对一,用多对一取代

4、配置对象缓存,不使用集合缓存

5、一对多集合使用Bag,多对多集合使用Set

6、继承类使用显式多态

7、表字段要少,表关联不要怕多

 

七)Hibernate几个核心接口

1、Configuration接口:配置Hibernate,根据其启动hibernate,创建SessionFactory 对象;

2、SessionFactory接口:初始化Hibernate,充当数据存储源的代理,创建session 对象,sessionFactory 是线程安全的,意味着它的同一个实例可以被应用的多个线程共享,是重量级、二级缓存;

3、Session接口:负责保存、更新、删除、加载和查询对象,是线程不安全的,避免多个线程共享同一个session,是轻量级、一级缓存;

4、Transaction接口:管理事务;

5、Query和Criteria接口:执行数据库的查询。

 

八)Hibernate检索策略

1、立即检索策略

  优点:当使用检索策略,不管对象处于持久化状态,还是游离状态,都可以从一个对象导航到与他关联的另一个对象。

  缺点:由于select语句的数目太多,需要频繁的访问数据库,

2、延迟检索策略

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

  缺点:应用程序如果希望访问游离状态的代理类实例,必须保证它在持久化状态时已经被初始化。要不然会出现异常。

3、左外连接检索策略

  优点:对应用程序完全透明,不管对象处于持久化,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象。使用了外链接,select语句数目少。

  缺点:可能会加载应用程序不需要访问的对象,白白浪费许多内存空间;复杂的数据库表连接也会影响检索性能。

 

九)Hibernate 主键ID生成策略

1、increment:由hibernate自动递增的方式生成标识符,每次增量为1,优点是适用于所有数据库,缺点是在集群环境下可能会出现相同的主键值,且OID必须为数值类型。

2、identity:由底层数据库自动增长生成标识符,需要数据库支持自动增长,比如sqlserver,mysql支持,且OID必须为数值类型。

3、sequence:由底层数据库序列生成标识符,需要数据支持序列,比如oracle支持,且OID必须为数值类型。

4、native:native由hibernate根据使用的数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强。如果能支持identity则使用identity,如果支持sequence则使用sequence。

5、uuid:Universally Unique Identifier,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。

特点:uuid长度大,占用空间大,跨数据库,不用访问数据库就生成主键值,所以效率高且能保证唯一性,移植非常方便,推荐使用。

6、guid:Globally Unique Identifier全球唯一标识符,也称作 UUID,是一个128位长的数字,用16进制表示。算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成GUID。从理论上讲,如果一台机器每秒产生10000000个GUID,则可以保证(概率意义上)3240年不重复。

 

十)Hibernate缓存机制

1、一级缓存声明周期很短和session的生命周期一致,一级缓存也叫session级的缓存或事物级缓存,一级缓存是缓存对象的,并不能缓存属性。

2、二级缓存也称为进程级缓存或SessionFactory级缓存,二级缓存可以被所有的session缓存共享。二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存,二级缓存的原则是当读远大于写的时候使用,二级缓存也主要是缓存实体对象的。

 

十一)Hibernate几种缓存策略

1、只读型(Read-Only):提供Serializable数据隔离级别,对于从来不会被修改的数据,可以采用这种访问策略。

2、读写型(Read-write):提供ReadCommited数据隔离级别,对于经常读但是很少被修改的数据,可以采用这种隔离类型,因为它可以防止脏读。

3、非严格读写(Nonstrict-read-write):不保证缓存与数据库中数据的一致性,提供ReadUncommited事务隔离级别,对于极少被修改,而且允许脏读的数据,可以采用这种策略。

4、事务型(Transactional):仅在受管理环境下适用,它提供了RepeatableRead事务隔离级别,对于经常读但是很少被修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读。

 

十二)Hibernate延时加载

1、延迟加载的几种情况:

  当调用Session上的load()方法加载实体时,就会采用延迟加载。

  当Session加载某个实体时,会对这个实体中的集合属性值采用延迟加载。

  当Session加载某个实体时,会对这个实体所单端关联(one-to-one,many-to-one)的另一个实体对象采用延迟加载。

2、延迟加载的过程:

Hibernate从数据库获取某一个对象数据、获取某一个对象的集合属性时,获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据,hibernate并不从数据库加载真正的数据。而是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都为默认值,只有在真正的需要该对象的数据时才创建这个真实的对象,真正的从数据库中加载数据。

 

十三)Hibernate中get()和load()的区别

1、get():使用get()来根据ID进行单条查询,当get()方法被调用的时候就会立即发出SQL语句,并且返回的对象也是实际的对象,使用get()和普通的单条查询并没有多大的区别。

2、load():当调用load()方法的时候会返回一个目标对象的代理对象,在这个代理对象中只存储了目标对象的ID值,只有当调用除ID值以外的属性值的时候才会发出SQL查询的。

缓存:get()和load()都会使用缓存,都是首先从一级缓存Session中查找,当找不到的时候再去二级缓存中查找,当查询不到的时候get()返回的是null,而load()则返回代理对象。

 

十四)Hibernate实体的级联(cascade)

1、cascade=”none”,默认值,告诉Hibernate忽略关系。

2、cascade=”save-update”告诉Hibernate在下面这些情况导航关联:当事务提交时,当对象传给save()或update()方法并保存新初始化的瞬时实例及把更改持久到分离实例时。

3、cascade=”delete”告诉Hibernate当对象传给delete()时导航关联并删除持久实例。

4、cascade=”all”意思是save-update和delete都级联。

5、cascade=”all-delete-orphan”,跟cascade=”all”一样,但是除此之外,Hibernate 删除任何已经从关联(例如,从集合)删除(不再被引用)的持久实体实例。

6、cascade=”delete-orphan”,Hibernate 将会删除任何已经从关联(例如,从集合)删除(不再被引用)的持久实体实例。

 

十五)Session缓存的作用

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

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

 

十六)Hibernate里面sorted collection和ordered connection有什么区别

1、sorted collection是在内存中通过java比较器进行排序的。

2、ordered collection是在数据库中通过order by进行排序的。

 

十七)Hibernate中怎样实现类之间的关系

它们通过配置文件中的many-to-one、one-to-many、many-to-many来实现类之间的关联关系的。

 

十八)hibernate中getCurrentSession和openSession区别

1、getCurrentSession会绑定当前线程,而openSession不会,因为我们把hibernate交给我们的spring来管理之后,我们是有事务配置,这个有事务的线程就会绑定当前的工厂里面的每一个session,而openSession是创建一个新session。

2、getCurrentSession事务是有spring来控制的,而openSession需要我们手动开启关闭和手动提交事务。

3、getCurrentSession需要我们手动设置绑定事务的机制,有三种设置方式,jdbc本地的Thread、JTA、第三种是spring提供的事务管理机制org.springframework.orm.hibernate4.SpringSessionContext,而且srping默认使用该种事务管理机制。

 

十九)SessionFactory是线程安全的么

SessionFactory是Hibrenate单例数据存储和线程安全的,以至于可以多线程同时访问。一个SessionFactory 在启动的时候只能建立一次。SessionFactory应该包装各种单例以至于它能很简单的在一个应用代码中储存。

 

二十)Hibernate 实体类必须要有无参构造函数吗?为什么?

Hibernate中每个实体类必须提供一个无参构造函数,因为Hibernate框架要使用Reflection API,通过调用ClassnewInstance()来创建实体类的实例,如果没有无参的构造函数就会抛出异常。

 

识别二维码关注个人微信公众号

本章完结,待续,欢迎转载!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值