一、乐观锁和悲观锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
 
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
 
两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。
 
悲观锁:
String hqlStr = "from TUser as user where user.name='Erica'";
Query query = session.createQuery(hqlStr);
query.setLockMode("user",LockMode.UPGRADE); //加锁
List userList = query.list();//执行查询,获取数据
Hibernate的加锁模式有:
Ø LockMode.NONE : 无锁机制。
Ø LockMode.WRITE :Hibernate在 Insert 和 Update 记录的时候会自动获取。
Ø LockMode.READ : Hibernate在读取记录的时候会自动获取。
       ---以上这三种锁机制一般由 Hibernate 内部使用,如 Hibernate 为了保证 Update 过程中对象不会被外界修改,会在 save 方法实现中自动为目标对象加上 WRITE 锁。
Ø LockMode.UPGRADE :利用数据库的 for update 子句加锁。
Ø LockMode. UPGRADE_NOWAIT :Oracle 的特定实现,利用 Oracle 的for update nowait 子句实现加锁。
              -- 上面这两种锁机制是我们在应用层较为常用的,加锁一般通过以下方法实现:
Criteria.setLockMode
Query.setLockMode
Session.lock 

二、多态

第一种方案:一个子类对应一张表。
实现方式:在父类的配置文件中配置子类的实现方式,当然,也可以在子类中单独配置:
         <!-- 可单独写在Student.hbm.xml里 -->
<union-subclassname="com.jomoo.entity.Student"table="student"extends="com.jomoo.entity.People">
<propertyname="studentNumber"column="studentNumber"type="string"></property>
</union-subclass>
<!-- 可单独写在Teacher.hbm.xml里 -->
<union-subclass name="com.jomoo.entity.Teacher" table="teacher" extends="com.jomoo.entity.People">
<property name="salary" column="salary" type="string"></property>
</union-subclass>
 
第二种方案:使用一张表表示所有继承体系下的类的属性的并集。
这种策略是使用<subclass>标签来实现的。因为类继承体系下会有许多个子类,要把多个类的信息存放在一张表中,必须有某种机制来区分哪些记录是属于哪个类的。Hibernate中的这种机制就是,在表中添加一个字段,用这个字段的值来进行区分。在表中添加这个标示列使用<discriminator>标签来实现。
 
第三种方案:每个子类使用一张表只存储它特有的属性,然后与父类所对应的表以一对一主键关联的方式关联起来。
每个子类使用一张表只存储它特有的属性,然后与父类所对应的表以一对一主键关联的方式关联起来。这种策略是使用<joined-subclass>标签来定义子类的。父类、子类都对应一张数据库表。在父类对应的数据库表中,它存储了所有记录的公共信息,实际上该父类对应的表会包含所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字段。子类对应的数据表与父类对应的数据表,通过一对一主键关联的方式关联起来。

三、缓存

缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。
 
缓存的介质一般是内存,所以读写速度很快。但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质。
 
Hibernate 的缓存包括 Session 的缓存和 SessionFactory 的缓存,其中 SessionFactory 的缓存又可以分为两类:内置缓存和外置缓存。Session 的缓存是内置的,不能被卸载,也被称为 Hibernate 的第一级缓存。SessionFactory 的内置缓存和 Session 的缓存在实现方式上比较相似,前者是 SessionFactory 对象的一些集合属性包含的数据,后者是指 Session 的一些集合属性包含的数据。SessionFactory 的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在 Hibernate 初始化阶段根据映射元数据推导出来,SessionFactory 的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此 SessionFactory 不需要进行内置缓存与映射文件的同步。SessionFactory 的外置缓存是一个可配置的插件。在默认情况下,SessionFactory 不会启用这个插件。外置缓存的数据是数据库数据的拷贝,外置缓存的介质可以是内存或者硬盘。SessionFactory 的外置缓存也被称为Hibernate的第二级缓存。
 
一级缓存和二级缓存的区别:
Hibernate的一级缓存依赖于 session 的生命周期,无法卸载,只会被单个 session 所持有,一旦 session 的生命周期结束,一级缓存也就消失了,因此,一级缓存不会发生并发。
 
Hibernate的二级缓存是一个可配置的插件,为所有 session 所共同访问,因此他不适用于高并发的数据。由于二级缓存要保证数据的一致性,即数据源和缓存中数据的一致性,当频繁修改数据时,就需要不断访问数据库以保证一致性。这样缓存变得没有意义了。

四、状态

hibernate的三种状态
1、 瞬时态:刚 new 出来的一个对象,只是在内存中占据了一个空间,可被垃圾回收器回收,没有被保存到数据库,也没有与session相关联。
2、 持久态:对象被保存到数据库中,且缓存在 session 对象中,是一个持久的状态。
3、 脱离态:session 关闭了,原来 session 的缓存脱离了 session 的控制,但是又有一个数据库的记录与之相对应。但需要重新对这条记录改变时,脱离状态被重新回到持久状态。

五、其他

1、什么是SessionFactory?什么是Session?http session 和 hibernate session 有什么区别?

    SessionFactory 接口负责初始化 Hibernate。它充当数据存储源的代理,并负责创建 Session 对象。这里用到了工厂模式。需要注意的是 SessionFactory 并不是轻量级的,因为一般情况下,一个项目通常只需要一个 SessionFactory 就够,当需要操作多个数据库时,可以为每个数据库指定一个 SessionFactory 。
   在 hibernate 中的 session 并不是 http 中所说的 session,一般把 HttpSession 对象称为用户会话。
   而 hibernate 中的 Session 呢?是用来表示,应用程序和数据库的一次交互(会话)。在这个Session中,包含了一般的持久化方法(CRUD)。而且,Session 是一个轻量级对象(线程不安全),通常将每个 Session 实例和一个数据库事务绑定,也就是每执行一个数据库事务,都应该先创建一个新的 Session 实例,在使用 Session 后,还需要关闭 Session。

2、n+1问题?

一般而言说 n+1 意思是,无论在一对多还是多对一当查询出 n 条数据之后,每条数据会关联的查询1次他的关联对象,这就叫做 n+1。
下面是几种解决方案:
  • 设置 @ManyToOne 的fetch属性值为 fetchType.LAZY,这种方式解决后,后面的 n 条 sql 语句按需而发。但是有个弊端,就是如果需要级联查询就无法获取级联对象了。
  • 设置 @BatchSize(size=5)(该注解要加在类上面,跟@Entity在同一位置),这样发出的sql语句减少。这个设置在一定程度上提高了效率。
  • join fetch , 如使用"from Student s left join fetch s.group g", 进行表连接查询,此时就发1条SQL语句。
  • 使用QBC查询,默认效果与3相同:
              1、fetch="select" 会另外发出一条语句查询集合。
              2、设置 fetch="join" 采用外连接集合的 lazy 失效。
              3、这只 fetch="subselect" 另外发出一条 select 语句抓取前面查询到的所有的实体对象的关联集合 fetch只对 HQL 查询产生影响其他的则不会。

3、Hibernate中的 get 和 load 加载有什么区别?

当我们使用 session.load() 方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的 id 值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出 sql 语句,从数据库中去查询我们的对象。
 
相对于load的延迟加载方式,get 就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们 使不使用这个对象,此时都会发出sql语句去从数据库中查询出来。

4、脏读和幻读?

脏读:是指当一个事务正在访问数据,且对数据做了修改,但是还没有提交到数据库。另一个事务查询到这个数据、这个数据就是脏数据,依靠这个数据所做的操作就是不正确的、
幻读:比如第一个事务对数据库的全部行进行了修改,同时第二个事务插入一条数据到数据库中,这时第一个事务就会发现,数据库中有一条记录没有被修改,像发生了幻觉一样、

Hibernate 知识收纳.的更多相关文章

  1. hibernate 知识梳理

    一.hibernate背景介绍: 作者: Gavin King 分hibernate ORM(for relation db),OGM(for nosql db),hearch,validator,t ...

  2. HIBERNATE知识复习记录1-连接及常用方法

    要去面试了,复习一下HIBERNATE的相关知识吧,原来边看视频边写的代码如下,已经分不清先后次序了,大致看一看吧. 先看下总的配置文件hibernate.cfg.xml: <?xml vers ...

  3. 【Hibernate那点事儿】—— Hibernate知识总结

    前言: 上一篇简单的讲解了下Hibernate的基础知识.这里对Hibernate比较重要的一些知识点,进行总结和归纳. 手码不易,转载请注明!——xingoo 总结的知识点: 1 关于hiberna ...

  4. Hibernate知识总结(一)——Hibernate原理概述

    一.Hibernate是什么: 它是一个持久化框架,它对JDBC进行了轻量级的封装,简化对数据库的操作,提高开发效率.和另一个持久化框架MyBatis一样,他们操作数据库都是通过一个session对象 ...

  5. Hibernate 知识提高

    主键生成策略有: UUID,increment.Hilo.assigned:对数据库无依赖 identity:依赖Mysql或sql server,主键值不由hibernate维护 sequence: ...

  6. Hibernate知识总结(一)

    一.ORM ORM的全称是Object/Relation Mapping,即对象/关系映射,可以将其理解成一种规范,它概述了这类框架的基本特征:完成面向对象的编程语言到关系数据库的映射.可以把ORM看 ...

  7. HIBERNATE知识复习记录4-HQL和QBC

    Hibernate中共提供了三种检索方式:HQL(Hibernate Query Language).QBC.QBE(Query By Example). HQL 是Hibernate Query L ...

  8. HIBERNATE知识复习记录3-关联关系

    先上一张图,关于几种关系映射: 抄一段解释: 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用.关联关系分为上述七 ...

  9. HIBERNATE知识复习记录2-继承关系

    发现了一篇和我类似的学习尚硅谷视频写的文章,内容如下,比我说的详细全面,可以看一下: [原创]java WEB学习笔记87:Hibernate学习之路-- -映射 继承关系(subclass , jo ...

随机推荐

  1. 苹果_公司开发者账号_申请DUNS number

    申请DUNS number 注意事项:a.公司英文名称,例如:北京京城科技有限公司,Beijing Jingcheng Technology Co., Ltd.(Co.和Ltd.都是缩写,中间用“逗号 ...

  2. java 监听文件或文件夹变化

    今天遇到一个新需求,当从服务器下载文件后用指定的本地程序打开,不知道何时文件下载完成,只能考虑监听文件夹,当有新文件创建的时候打开指定程序. 在此给出一个完整的下载和打开过程: 1.下载文件 jsp页 ...

  3. django的使用INNODE的方式,排除错误MySQL Strict Mode is not set for database connection 'default'

    出现如下错误: 解决办法: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mxshop', 'HO ...

  4. 常用的git和repo命令

    首先下图是git的流程图 相关概念 svn与git命令的对比 git常用命令 git log // 查看当前库的git log信息 git status ./ // 查看当前库的状态 git diff ...

  5. 【2期】JVM必知必会

    JVM之内存结构图文详解 Java8 JVM内存结构变了,永久代到元空间 Java GC垃圾回收机制 不要再问我“Java 垃圾收集器”了 Java虚拟机类加载机制 Java虚拟机类加载器及双亲委派机 ...

  6. 十ITK读取一张dcm图像然后通过vtk显示

    一.功能 通过ITK读取一张图片(dcm格式),然后通过vtk显示出来. 版本:VS2019 itk5.0.1 vtk 8.2.0 二.程序主要思路 1-读取dcm格式图片 2-转换为vtk可以读取的 ...

  7. BitMap原理

    BitMap原理  

  8. 使用原生代码实现一个Events模块,可以实现自定义事件的订阅、触发、移除功能

    function Events() { // 放置所有添加的 监听事件 this._events = {} } Events.prototype = { on: function (name, fn, ...

  9. vue使用--vuex快速学习与使用

    什么是vuex? Vuex核心概念 Vuex安装与使用 1.安装 2.目录结构与vuex引入 3.store中变量的定义.管理.派生(getter) 4.vuex辅助函数的使用说明 Vuex刷新数据丢 ...

  10. python-16-初识函数

    前言 以前写的python代码都是像记流水账一样,那么函数时什么额?它可以在任何需要它的地方进行调用,函数分为: 内置函数,print(),len() 自定义函数 一.自定义函数 1.我们都知道内置函 ...