开篇介绍
大家好,我是 Java 最全面试题库的提裤姐,明天有点事更新晚了,然而断更是不可能断更的,这辈子都不可能断更的。好了,明天这篇是 JavaEE 系列的第六篇,次要总结了 Hibernate 相干的问题,在后续,会沿着第一篇开篇的常识线路始终总结上来,做到日更!如果我能做到百日百更,心愿你也能够跟着百日百刷,一百天养成一个好习惯。
Hibernate 执行流程?
- 读取并解析配置文件
- 读取并解析映射信息,创立 SessionFactory
- 关上 Sesssion
- 创立事务 Transation
- 长久化操作
- 提交事务
- 敞开 Session
- 敞开 SesstionFactory
什么是 Hibernate 的并发机制?怎么去解决并发问题?
Hibernate 并发机制:
1、Hibernate 的 Session 对象是非线程平安的
, 对于单个申请, 单个会话, 单个的工作单元(即单个事务, 单个线程), 它通常只应用一次, 而后就抛弃。
如果一个 Session 实例容许共享的话,那些反对并发运行的, 例如 Http request,session beans 将会导致呈现资源争用。
如果在 Http Session 中有 hibernate 的 Session 的话, 就可能会呈现同步拜访 Http Session。只有用户足够快的点击浏览器的“刷新”, 就会导致两个并发运行的线程应用同一个 Session。
2、多个事务并发拜访同一块资源
, 可能会引发第一类失落更新,脏读,幻读,不可反复读,第二类失落更新一系列的问题。
解决方案:①设置事务隔离级别
Serializable:串行化。隔离级别最高
Repeatable Read:可反复读
Read Committed:已提交数据读
Read Uncommitted:未提交数据读。隔离级别最差
②设置锁:乐观锁和乐观锁
乐观锁:应用版本号或工夫戳来检测更新失落, 在的映射中设置 optimistic-lock=”all”能够在没有版本或者工夫戳属性映射的状况下实现 版本查看,此时 Hibernate 将比拟一行记录的每个字段的状态 行级乐观锁:Hibernate 总是应用数据库的锁定机制,从不在内存中锁定对象!只有为 JDBC 连贯指定一下隔 离级别,而后让数据库去搞定所有就够了。类 LockMode 定义了 Hibernate 所需的不同的锁定级别:
- LockMode.UPGRADE
- LockMode.UPGRADE_NOWAIT
- LockMode.READ
Hibernate 中的三种数据状态?
长期态 (刹时态 /Transient)
不存在于 session 中,也不存在于数据库中的数据,被称为长期态。
比方:刚刚应用 new 关键字创立出的对象。
长久态 (Persistent)
存在于 session 中,事务还未提交,提交之后最终会进入数据库的数据,被称为长久态。
比方:刚刚应用 session.save()操作的对象。
游离态 (脱管态 /Detached)
存在于数据库中,但不存在于 session 中的数据,被称为游离态。
比方:应用了 session.save(),并且事务曾经提交之后,对象进入数据库,就变成了游离态。
Hibernate 的三种状态之间如何转换?
当对象由刹时状态 (Transient) 一 save()时,就变成了 长久化状态
;
当咱们在 Session 里存储对象的时候,理论是在 Session 的 Map 里存了一份,也就是它的缓存里放了一份,而后,又到数据库里存了一份,在缓存里这一份叫长久对象 (Persistent)。Session 一 Close() 了, 它的缓存也都敞开了, 整个 Session 也就生效了, 这个时候,这个对象变成了 游离状态 (Detached)
,但数据库中还是存在的。
当游离状态 (Detached)update() 时,又变为了长久状态 (Persistent)。
当长久状态 (Persistent)delete() 时,又变为了 刹时状态(Transient)
, 此时,数据库中没有与之对应的记录。
介绍一下 Hibernate 的缓存机制?
hibernate 分为 2 级缓存 一级缓存
又叫 session 缓存,又叫事务级缓存,生命周期从事务开始到事务完结,一级缓存是 hibernate 自带的,暴力应用,当咱们一创立 session 就已有这个缓存了。数据库就会主动往缓存寄存,二级缓存
是 hibernate 提供的一组凋谢的接口方式实现的,都是通过整合第三方的缓存框架来实现的,二级缓存又叫 sessionFactory 的缓存,能够跨 session 拜访。罕用的 EHcache、OScache,这个须要一些配置。
当咱们每次 查问数据的时候,首先是到一级缓存查看是否存在该对象,如果有间接返回,如果没有就去二级缓存进行查看,如果有间接返回,如果没有在发送 SQL 到数据库查问数据,
当 SQL 发送查问回该数据的时候,hibernate 会把该对象以主键为标记的模式存储到二级缓存和一级缓存,如果返回的是汇合,会把汇合打散而后以主键的模式存储到缓存。一级缓存和二级缓存只针对以 ID 查问的形式失效,get、load 办法。
说一下 Hibernate 的几个外围接口?
Configuration 接口
:配置 Hibernate,依据其启动 hibernate,创立 SessionFactory 对象SessionFactory 接口
:初始化 Hibernate,充当数据存储源的代理,创立 session 对象,sessionFactory 是线程平安的,意味着它的同一个实例能够被应 用的多个线程共享,是重量级、二级缓存Session 接口
:负责保留、更新、删除、加载和查问对象,是线程不平安的,防止多个线程共享同一个 session,是轻量级、一级缓存Transaction 接口
:治理事务Query 和 Criteria 接口
:执行数据库的查问。
get 和 load 的区别?
- get 是
立刻加载
,load 是延时加载
。 - get 会先查一级缓存,再查二级缓存,而后查数据库;
load 会先查一级缓存,如果没有找到,就创立代理对象,等须要的时候去查问二级缓存和数据库。(这里就体现 load 的提早加载的个性。)
- get 如果没有找到会返回
null
,load 如果没有找到会抛出异样
。 - 当咱们应用
session.load()
办法来加载一个对象时,此时并不会收回 sql 语句,以后失去的这个对象其实是一个代理对象,这个代理对象只保留了实体对象的 id 值,只有当咱们要应用这个对象,失去其它属性时,这个时候才会收回 sql 语句,从数据库中去查问咱们的对象;
绝对于 load 的提早加载形式,get 就间接的多,当咱们应用 session.get()
办法来失去一个对象时,不论咱们使不应用这个对象,此时都会收回 sql 语句去从数据库中查问进去。
Hibernate 有几种查问形式?
4 种:
HQL
通过 Hibernate 提供的查询语言进行查问。Hibernate Query lanagueEJBQL
(JPQL 1.0) 是 EJB 提供的查询语言QBC
(query by cretira)通过 Cretira 接口进行查问QBE
(query by Example) 通过 Example 编程接口进行查问
从性能强弱上排序:
NativeSQL > HQL > EJBQL(JPQL 1.0) >QBC(query by cretira) >QBE(query by Example)
QBC(Query By Criteria)查问形式是 Hibernate 提供的“更加面向对象”的一种检索形式。QBC 在条件查问上比 HQL 查问更为灵便,而且反对运行时动静天生查问语句。
Hibernate 中 save、update 和 saveOrUpdate 办法的不同之处?
save:
执行保留操作的, 对一个新 new 进去的对象进行保留, 数据库中没有这个对象, 如果数据库中有, 会报错说有反复的记录
update:
如果是对一个曾经存在的托管对象进行更新, 要应用 update 办法了, 数据中有这个对象
saveOrUpdate:
这个办法是更新或者插入, 有主键就执行更新, 如果没有主键就执行插入。是依据实体类对象的状态做的不同操作
在数据库中条件查问速度很慢的时候, 如何优化?
- 建索引
- 缩小表之间的关联
- 优化 sql,尽量让 sql 很快定位数据,不要让 sql 做全表查问,应该走索引, 把数据量大的表排在后面
- 简化查问字段,没用的字段不要,曾经对返回后果的管制,尽量返回大量数据
什么是 Hibernate 提早加载?
提早加载机制:
提早加载机制是为了防止一些无谓的性能开销而提出来的,所谓提早加载就是当在真正须要数据的时候,才真正执行数据加载操作。在 Hibernate 中提供了对实体对象的提早加载以及对汇合的提早加载,另外在 Hibernate3 中还提供了对属性的提早加载。
提早加载的过程:
通过代理(Proxy)机制来实现提早加载。Hibernate 从数据库获取某一个对象数据时、获取某一个对象的汇合属性值时,或获取某一个对象所关联的另一个对象时,因为没有应用该对象的数据(除标识符外),Hibernate 并不从数据库加载真正的数据,而只是为该对象创立一个代理对象来代表这个对象,这个对象上的所有属性都为默认值;只有在真正须要应用该对象的数据时才创立这个真正的对象,真正从数据库中加载它的数据。
Hibernate 和 Mybatis 的区别?
相同点:
- Hibernate 与 MyBatis 都能够是通过 SessionFactoryBuider 由 XML 配置文件生成 SessionFactory,而后由
SessionFactory 生成 Session,最初由 Session 来开启执行事务和 SQL 语句。其中 SessionFactoryBuider,
SessionFactory,Session 的生命周期都是差不多的。
- Hibernate 和 MyBatis 都反对 JDBC 和 JTA 事务处理。
Mybatis 劣势:
- MyBatis 能够进行更为粗疏的 SQL 优化,能够缩小查问字段。
- MyBatis 容易把握,而 Hibernate 门槛较高。
Hibernate 劣势:
- Hibernate 的 DAO 层开发比 MyBatis 简略,Mybatis 须要保护 SQL 和后果映射。
- Hibernate 对对象的保护和缓存要比 MyBatis 好,对增删改查的对象的保护要不便。
- Hibernate 数据库移植性很好,MyBatis 的数据库移植性不好,不同的数据库须要写不同 SQL。
- Hibernate 有更好的二级缓存机制,能够应用第三方缓存。MyBatis 自身提供的缓存机制不佳。