博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Hibernate 处理事务
阅读量:7123 次
发布时间:2019-06-28

本文共 3627 字,大约阅读时间需要 12 分钟。

1. Hibernate 的持久化类

1.1 什么是持久化类

  • 持久化类: 就是一个 Java 类(JavaBean),这个 Java类与表建立了映射关系就可以是持久化类;
  • 持久化类 = JavaBean + xxx.hbm.xml;

1.2 持久化类的编写规则

  • 提供一个无参数的构造方法,因为底层需要进行反射;
  • 提供一个唯一的标识 OID, 即映射数据表主键;
    数据库中通过主键, Java 对象通过地址确定对象. 持久化类通过唯一标识 OID 确定记录.
  • 所有属性提供公有的 set 或者 get 方法;
  • 标识属性应尽量使用基本数据类型的包装类;

1.3 自然主键和代理主键

  • 自然主键: 对象本身的一个属性. 例如,创建一个人员表,使用身份证号(唯一的)作为表的主键.
  • 代理主键: 不是对象本身的一个属性. 例如,创建一个人员表,为每个人员单独创建一个作为主键的字段.
  • 创建表时,尽量使用代理主键.

1.4 主键生成的策略

// 主键的生成策略
  1. increment: 适用于 short, int, long 作为主键,不是使用的数据库自动增长机制;
    • Hibernate 中提供的一种增长机制;
    • 先进行查询: select max(id) from user, 再进行插入,将查询出的最大值+1 作为新记录的主键;
    • 缺点:不能在集群环境下或者有并发访问的情况下使用;
  2. identity: 适用于 short, int, long 作为主键,但是这个必须使用在自动增长的数据库中.
    • 底层使用的是数据库的自动增长机制;
  3. sequence: 适用于short, int, long 作为主键.
    • 底层使用的是序列的增长方式,例如 Oracle 数据库.
  4. uuid: 适用于 char, varchar 类型的作为主键;
    • 使用随机的字符串作为主键;
  5. native: 使用本地策略,根据底层的数据库不同,自动选择适用于该种数据库的生成策略.
    • 如果底层使用的 MySql 数据库,相当于 identity;
    • 如果底层使用的是 Oracle 数据库,相当于 sequence;
  6. assigned: 主键的生成不用 Hibernate 管理,必须手动设置主键;

2. Hibernate 持久化对象的状态

2.1 Hibernate 持久化类的状态

  1. Hibernate 为了管理持久化类,将持久化类分成了三个状态:
    • 瞬时态(Transient Object), 没有持久化标识 OID,没有被纳入到 Session 对象的管理;
    • 持久态(Persistent Object)
      • 有持久化标识OID,已经被纳入到 Session 对象的管理;
      • 注意: 持久化持久态的对象有自动更新数据库的能力!! 因为 Session 的一级缓存.
    • 托管态(Detached Object), 有持久化标识 OID,没有被纳入到 Session 对象的管理;

2.2 Hibernate 持久化对象的状态转换

1222878-20171020083054115-1219309143.jpg

  1. 瞬时态
    • 获得瞬时态对象: User user = new User();
    • 瞬时态对象转换成持久态: save() 或 saveOrUpdate();
    • 瞬时态对象转换成托管态(不推荐): user.setId();
  2. 持久态
    • 获得持久态的对象: get() 或 load();
    • 持久态转换成瞬时态对象: delete();
    • 持久态对象转成托管态对象: session 的 close() 或 evict() 或 clear()
  3. 托管态
    • 托管态转换成瞬时态: user.setId(null);
    • 托管态转换成持久态: update() 或 saveOrUpdate();

3. Hibernate 的一级缓存

3.1 什么是缓存

  • 缓存其实就是一块内存空间,将数据源(数据库或者文件)中的数据存放到缓存中,再次获取的时候,直接从缓存中获取.
    可以提升程序的性能.

3.2 Hibernate 框架提供了两种缓存

  1. 一级缓存
    • 自带的,不可卸载的;
    • 一级缓存的生命周期与 session 一致, 一级缓存称为 session 级别的缓存;
  2. 二级缓存
    • 二级缓存可以在多个 session 中共享数据;
    • 二级缓存称为 sessionFactory 级别的缓存;
    • 二级缓存是为了增强一级缓存,一级缓存的生命周期比较短暂;
    • 二级缓存默认没有开启,需要手动配置才可以使用;
  3. session 对象的缓存概述
    • Session 对象中有一系列 java 的集合,这些集合构成了一级缓存;
  4. Session 中与一级缓存相关的方法
    • session.clear(): 清空一级缓存;
    • session.evict(Object entity): 从一级缓存中清除指定的实体对象;
    • session.flush(): 刷出缓存;
  5. Hibernate 框架是如何做到数据发生变化时,进行同步操作的呢?

1222878-20171020083109865-1185935914.png

4. Hibernate 中的事务和并发

4.1 Hibernate 框架中设置隔离级别

  1. 需要在 hibernate.cfg.xml 的配置文件中通过标签来配置;
    • <property name="hibernate.connection.isolation">4</property>
    • "1"表示 Read uncommitted isolation
    • "2"表示 Read committed isolation
    • "4"表示 Repeatable read isolation
    • "8"表示 Serializable isolation

4.2 丢失更新的问题

  1. 如果不考虑隔离性,也会产生写入数据的问题,即丢失更新的问题;
  2. 例如: A 和 B 两个事务同时对某一条记录做修改,就会引发丢失更新的问题;
  3. 解决方案
    • "悲观锁"
      • 采用的是数据库提供的一种锁机制,如果采用了这种机制,在SQL语句的后面添加for update子句
      • 当 A 事务在操作该条记录时,会把该条记录锁起来,其他事务是不能操作这条记录的;
      • 只有当 A 事务提交后,锁释放了,其他事务才能操作该条记录;
    • "乐观锁"
      • 采用版本号的机制来解决,会在表结构添加一个字段 version=0,默认值为 0;
      • 当 A 事务在操作完该条记录,提交事务时,会先检查版本号,只有版本号值相同,才可以提交事务.
        同时,更新版本号 version=1;
      • 当 B 事务在操作完该条记录,提交事务时,会先检查版本号,如果发现版本号不同,程序会抛出异常.
  4. Hibernate 框架解决丢失更新的问题
    • "悲观锁":较少使用,效率慢
    • "乐观锁"
      • 在对应的 JavaBean 中添加一个属性,名称可以是任意的.并提供 get 和 set 方法.
        例如:private Integer version;
      • 在映射的配置文件中,提供 <version name="version"/> 标签即可;

4.3 绑定本地 Session

  1. JavaWeb 中的事务,需要在业务层使用 Connection 来开启事务
    • 一种是通过参数的方式传递;
    • 另一种是把 Connection 绑定到 ThreadLocal 对象中;
  2. Hibernate 框架,使用 session 对象开启事务.框架提供了 ThreadLocal 的方式,传递 session 对象

1222878-20171020083133396-1143355168.png

// 需要在 hibernate.cfg.xml 的配置文件中提供如下配置    
thread
// 重写 HiberanteUtils 工具类 public class HibernateUtils { private static final Configuration CONFIG; private static final SessionFactory FACTORY; static{ CONFIG = new Configuration().configure(); FACTORY = CONFIG.buildSessionFactory(); } public static Session getCurrentSession(){ // 从 ThreadLocal 中获取当前 session 对象 // 该对象不用再手动关闭,线程结束了,会自动关闭. return FACTORY.getCurrentSession(); } }

参考资料

转载于:https://www.cnblogs.com/linkworld/p/7697697.html

你可能感兴趣的文章
【全开源】可视化DIY微信/百度/支付宝小程序saas平台源码
查看>>
视频课程-数组去重你知道多少种方法?-冰山工作室-沙翼-web前端
查看>>
elementUI分页在IE浏览器中存在的bug
查看>>
是哪一瞬间让后端们决定入职的?
查看>>
[实践总结]纯css实现动态边框
查看>>
字幕字体滚动插件——scroxt.js
查看>>
小程序navigationStyle: custom 下web-view高度异常填坑
查看>>
性能与可伸缩性
查看>>
这一篇就够了——APP瘦身总结
查看>>
写篇文章不难
查看>>
解决TextView上的文字与其他view的间距问题
查看>>
从机器智能得到的启示:对年轻人第一份工作的建议
查看>>
object c 一个改变图标颜色的方法
查看>>
Pinpoint-java性能分析最佳实践_开源PaaS Rainbond
查看>>
Kafka 消息序列化和反序列化(上)
查看>>
箭头函数
查看>>
npm--依赖管理 2
查看>>
设计模式 开闭原则
查看>>
UI设计小白怎样学才能快速入门?
查看>>
用Redis轻松实现秒杀系统
查看>>