一、乐观锁和悲观锁

悲观锁(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. C编程小结1

    1. ‘\0’表示字符串结束符 2. 变量之间互相赋值一定要考虑他们的数据类型,要强制转换匹配上了或者进行一些处理才能赋值,同时读程序的时候也要注意这一点,否则可能看不懂.如: sData[0]=wD ...

  2. centos7设置静态ip-修改配置文件方式

    修改IP地址为静态地址需要修改配置文件,首先打开配置文件,在控制台输入cd /etc/sysconfig/network-scripts 输入ifconfig,这样就可以看到你的ip地址等信息了. v ...

  3. idea git提交代码步骤

    这位兄台已经写的很清楚了... 我这里直接给你们链接把... https://blog.csdn.net/u013452337/article/details/79956604 Git 初次提交,以及 ...

  4. 一个diango项目的结构

    一个项目的结构 day43项目 .idea 配置 pycharm自动帮配的配置,打开别人的diango项目时要先删了此项 app01 方便在一个大的Django项目中,管理实现不同的业务功能 migr ...

  5. [错误]Caused by: org.apache.spark.memory.SparkOutOfMemoryError: Unable to acquire 65536 bytes of memory, got 0

    今天,在运行Spark SQL代码的时候,遇到了以下错误: Caused by: org.apache.spark.SparkException: Job aborted due to stage f ...

  6. Flask 教程 第五章:用户登录

    本文翻译自The Flask Mega-Tutorial Part V: User Logins 这是Flask Mega-Tutorial系列的第五部分,我将告诉你如何创建一个用户登录子系统. 你在 ...

  7. 【koa2】用户注册、登录校验与加盐加密

    加密与解密 先介绍一下关于服务端用户名跟密码的存储状态,我们知道当前端在注册一个新用户时,会在表单内填入用户名和密码,并通过post请求提交到服务器,服务器再把用户名和密码从ctx.request.b ...

  8. 【转载】作为Android开发者,你真的熟悉Activity吗?

    学过android的人都知道,activity是最常用的四大组件之一,但你真的了解透彻activity了吗?接下来,本人将从activity的正常和异常生命周期.启动模式.IntentFilter匹配 ...

  9. linux上下键,rlwrap来解决

    需要安装两个包1.readline,配置好yum直接安装[root@test152 ~]# yum install readline*2.rlwrap这个下载连接当前有效,找了很多没找到有用的http ...

  10. bay——RAC 关闭和启动顺序,状态查看.txt

    oracle 11g rac 关闭和启动顺序,状态查看https://www.cnblogs.com/hellojesson/p/4501112.html----------------------- ...