美文网首页程序员
持续输出面试题之Hibernate篇

持续输出面试题之Hibernate篇

作者: 我可能是个假开发 | 来源:发表于2020-08-07 15:17 被阅读0次

    开篇介绍

    大家好,我是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 lanague
    • EJBQL(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 本身提供的缓存机制不佳。

    相关文章

      网友评论

        本文标题:持续输出面试题之Hibernate篇

        本文链接:https://www.haomeiwen.com/subject/fvxjlktx.html