hibernate面试题整理

1.hibernate中的SessionFactory是线性安全的吗?Session是线性安全的吗?(两个线程能共享这个Session吗?)

  1. SessionFactory是线性安全的(一般在启动的时候创建,用于创建Session)
  2. Session是非线性安全的,且不可被共享

2.Hibernate中Session中的load和get方法的区别?

1. 如果找不到符合条件的记录:load会抛出异常;get会返回一个null值
2. load返回的是一个实体类对象的代理;get返回的是实体类对象
3. hibernate3以前,get只能从一级缓存中寻找,若找不到目标,
跳过二级缓存直接返回null,而hibernate3以后就可以了;
而load可以在二级缓存中寻找

3.hibernate中的对象有哪几种状态?说详细点

1.对象状态有瞬时态、游离态、持久态。
2.瞬时态的实例:比如刚从new中产生的对象;
  游离态的实例:比如session进行了close、clear、flush。
  持久态:顾名思义,已经持久化到数据库中的对象。
3.三者之间的转化:
  瞬时态→持久态:save(),persist(),saveOrUpdate()(引发sql的插入)
  游离态→持久态:update(),merge(),lock(),saveOrUpdate()(引发sql的更新)
 
 注意: nerge可以完成save和update的功能;
 	   lock是将一个有更改过的脱管的对象转化为持久化。
 	   update是将一个已经更改过脱管的对象进行持久化。

4.说一下Session加载实体对象的过程

1.从一级缓存中通过实体类的主键进行寻找,如果有,返回。
2.如果一级缓存中没有,那么会去一个叫Noexists的记录中去查找,如果有,返回null
(这个记录相当于一个黑名单吧,会记录一些重复出现的无效查询)
3.如果黑名单中没有,从二级缓存中去查找(前提是配置了二级缓存)
4.如果一二级缓存都没有,就说明没有查询过,那么发起sql语句去查询。
如果数据库中查询不到,那么说明这个sql语句是一个无效查询,把它放到第二步中
的黑名单去。并返回一个null
5.如果查询到了,那么根据映射和sql返回的ResultMap,创建对应的实体类对象
6.将对象放到Session(一级缓存)中去管理
7.如果配置了拦截器(执行他的onload方法)
8.如果配置了二级缓存,将对象放到二级缓存中
9最后,返回一个实体类对象

5.说一下hibernate中的悲观锁和乐观锁
1.首先说一下锁的概念:就是有一些业务逻辑在执行的过程中要求对数据进行一些排他性的访问,于是需要通过一些机制来保证这个过程中的数据被锁住且不会被外界修改,这个就是所谓的锁机制

悲观锁:认为数据处理过程中极有可能存在修改数据的并发事务(保持悲观态度)
于是将数据设置为锁定状态(其实现必须依赖于数据库本身的锁机制)
乐观锁:对事物的并发处于乐观态度,通过更加宽松的锁机制,来解决由于悲观锁
排他性的数据访问对系统性能造成的影响(例:数据版本标识)

加锁的方式:
悲观锁:数据库sql语句中添加for update字段,如:select * from user for update
乐观锁:给实体类加一个int类型的版本号属性就可以了(还要有get,set方法),然后设置对象配置文件,在id字段后面设置:

<version name="version" column="version" type="integer"></version>

6.如何理解hibernate的延迟加载机制,在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?
1.首先说一下什么是延迟加载:就是并不是在读取的时候就把数据加载,而是在你真正使用的时候在加载。举个例子:

User u=userService.getUser(1);(这里就是个简单的根据主键查询sql语句)
但是,如果你就这么一句话,别的这么都不加,那么代码运行的时候,看日志可以发现
程序没有跑执行sql语句,因为这个代码没有被真正的用到
那么如果再加一行代码,如:
System.out.println(u.toString());
那么此时要输出user对象的各个属性,则代表这个对象要真正被使用到了,那么
此时程序会执行sql语句。

2.如何处理矛盾?

1.关闭延迟加载特性
2.Session关闭前就获取数据(可以先用hiber.isInitialized判断对象是否被加载
在使用hibernate.initialize来获取对象)
3.利用拦截器、过滤器来延长Session的生命周期直至视图获取数据。

7.如何实现一对多,多对一,多对多的关系映射?
1.一对多:one-to-many
2.多对一:many-to-one
3.多对多:many-to-many

8.简述hibernate常见的优化策略
1.制定合理的缓存策略(比如二级缓存)
2.指定合理的Session管理机制
3.尽量使用延迟加载特性(默认开启)

9.简述一下hibernate的一二级缓存和查询缓存
1.一级缓存:(Session级别)默认开启,当保存/修改持久化实体的时候,会将这些改变先保存到Session中,而不是立马提交到数据库中进行更新
作用:减少与数据库的交互,提高访问性能
2.二级缓存:(SessionFactory级别)默认关闭,需要手动配置并且指定一个实体类,他会记录访问过该实体类的每一个对象
注意:一二级缓存都为对整个实体类进行缓存,而不是缓存他的普通属性

3.查询缓存:将hql,sql语句以及查询结果作为键值进行缓存(因此如果存在第二次同样的查询,就不会走数据库中,而是从缓存中直接读取)

10.简述下hibernate的使用流程?
记住七步走:
1.加载配置文件

Configuration cfg=new Configuration.configure();

2.拿到SessionFactory工厂(从配置文件中取)

SessionFactory sessionFactory=cfg.buildSessionFactory();

3.从工厂中获取Session

Session session=sessionFactory.openSession();

4.开启事务

session.beginTransation();

5.操作:
save、update等等
6.提交事务:

session.getTransation.commit();

7.关闭事务

session.close();

11.为什么要使用hibernate?
1.hibernate对jdbc访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
2.hibernate作为一个基于jdbc的主流的持久化、全自动ORM框架,简化了Dao层
3.使用java反射机制,而非字节码增强机制来实现透明化
4.性能好,轻量级,支持各种数据库。

12.hibernate中的update()和saveOrUpdate()的区别是什么?
1.saveOrUpdate():如果对象已经在本session中持久化了,那么不做任何事情。
2.如果另一个和本session关联的对象拥有相同的持久化标识(identifier),那么会抛出一个异常(如果那个对象没有identifier或者有identifier但是是一个刚刚new出来的对象,那么调用save())
3.如果对象附带版本信息identifier,且表明他是一个刚new出来的对象
那么调用save(),否则调用update()

13.如何优化hibernate?
1.使用双向一对多关联,不使用单向的一对多
2.用多对一取代一对多。
3.配置对象缓存,少使用集合缓存
4.一对多使用Bag存储对象,多对多使用Set
5.表字段尽量少,(即大表拆成小表)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zong_0915

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值