Hibernate 生成策略和缓存策略

主键生成策略

一、主键分类

1. 自然主键

主键本身就是表中的一个字段,实体中一个具体的属性,对象本身唯一的特性

比如:创建一个学生表:姓名、年龄、身份证号(自然主键)

2. 代理主键

主键本身不是表中必须的一个字段

同样创建一个学生表:姓名、年龄 、身份证号、SID(代理主键)

在实际开发当中尽量要使用代理主键

  • 设计以学生身份证号为主键
  • 在业务上添加学生身份证号,不小心录入错误
  • 主键修改是如果两个相同是允许修改的。所以一旦参于业务,就可能存在一些问题
  • 主键一般只作为条件,查询,不参与修改,使用代理主键就和表当中的业务信息没有关系

开发中为什么要使用代理主键

  • 一旦自然主键参与到业务逻辑当中,后期有可能修改源代码
  • 一个好的程序设计要满足开闭原则(Open Closed Principle)
    • 对程序的扩展是open开放的
    • 对修改源码是close的

二、主键的生成策略

  • 在使用代理主键的过程当中,尽量要做到自动生成主键,不能让用户手动设置主键
  • 一般交给数据库自动增长,让程序生成唯一的标识
  • 在hibernate当中,为了减少程序的编写,内部提供了多种的主键生成策略

1. increment

  • 自动增加策略(long、short、int)
  • 原理
    • 首先先发送一条语句:select max(id) from 表
    • 然后让id加1
  • 在单线程中使用,不要在多线程中使用
    • 两个线程同时对数据库当中的id字段查询
    • 两个人查询的内容都是1
    • 其中一个肯定会报错

2. identity

  • 自动增长
  • 原理
    • 使用是数据库底层的增长策略
    • 适用于有自动增长机制的数据库
      • Mysql有自动增长
      • Oracle是没有自动增长的:通过序列来完成这种效果的

3. sequence

  • 自动增长
  • 原理
    • 采用序列的方式
    • 必须得要支持序列
      • Oracle支持序列
      • Mysql不支持序列

4. uuid

  • 适用于字符串类型的主键
  • 使用hibernate中随机生成字符串的主键

5. native

  • 本地策略
  • 在 identity 和 sequence 自动切换

6. assigned

  • hibernate不会帮你管理主键
  • 自己手动调用或通过程序来去生成主键

持久化

一、什么是持久化

  • 将内存中的一个对象持久化到(存储到)数据库的过程
  • hibernate框架就是一个持久化的框架

二、什么是持久化类

  • 一个Java类与数据库建立的映射关系
  • 持久化类 = Java类 + 映射文件

三、持久化类编写规则

1.对持久化类提供一个无参的构造方法

  • 底层会通过反射创建对象
  • 如果没有无参构造,反射是无法创建对象的

2.对内部私有的字段要提供get与set方法

  • 不提供的话。hibernate就无法获取对象的值

3.对象持久化类提供一个OID与数据库表当中的主键对应

  • Java中通过对象的地址来区别是否为同一个对象
  • 数据库中通过主键来区别是否是同一条记录
  • Hibernate中通过持久化类的OID属性来区分是否是同一个对象

4.持久化类中的属性尽量使用包装类型

  • 包装类型的默认值为NULL
  • 基本数据类型的默认值为数字

5.持久化类不要使用final修饰

  • 跟延时加载有关系
  • 延时加载是Hibernate优化的手段
  • 返回的是一个代理对象
  • 使用动态代理 ,低层使用的是字节码增强技术,继承这个类来进行代理。
  • 如果使用了final,就不能被继承,不能被继承,代理对象就无法创建,延时加载就无效了。

持久化类的划分

  • Hibernate是持久层的框架,通过持久化类完成ORM操作
  • 持久化类:Java类+映射文件

Hibernate为了更好的管理持久化类,将持久化类对象分为三种状态

1. 瞬时态

  • 没有唯一的OID
  • 没有被session管理
  • 这种对象我们称为瞬时态对象

2.持久态

  • 有唯一的OID
  • 有被session管理
  • 这种对象我们称为持久态对象

3.游离态/托管态/离线态

  • 有唯一的OID
  • 没有被session管理

三种状态区分

1. 瞬时态

刚new出对象时,还没有设置id,还没有被session所管理。

2. 持久态

已经有了id,调用session方法,把对象给session,才被session所管理 。

添加到session之后, 对象一直处理持久态。当对象处理持久态时, 可以自动更新数据库。

持久态对象特征
  • 自动更新数据,只要成为持久态对象,不用调用update也会自动更新数据
  • 如果值和数据库当中的值一样, 就不会发送update
  • 原理:依赖了hibernate当中的一级缓存

3. 游离态

把session关闭掉时close时,对象处理游离态。

代码演示

三种状态之间的转换

一级缓存

一、什么是缓存

  • 缓存是一种优化的方式,分为一级缓存和二级缓存。
  • 将数据存入到内存当中,使用的时候直接从缓存中获取,不用直接到存储源中取数据了。

二、一级缓存

  • session级别的缓存
  • 生命周期与Session一致:一级缓存是由Session中的一系列Java集合构成的
  • 是自带的, 不可卸载

三、二级缓存

  • SessionFactory级别的缓存
  • 需要自己去配置,默认是开启的,在企业当中一般都不用了,现在都 redis。

四、一级缓存特点

当应用程序用Session接口的Save(),update(),saveOrUpdate()时,如果session缓存中没有相应的对象,就会自动的从数据库查询相应的信息,写到缓存当中。

当调用Session接口的load,get()方法,以及Query接口的list iterator方法时, 会判断缓存中是否存在该对象,有则返回, 不会查询数据库,如果缓存中没有要查询的对象,再到数据库当中查询对应的对象,并添加到一级缓存中。

当调用session.close方法时,缓存会被清空。

代码:

五、一级缓存内部结构

一级缓存当中有一个区域:快照区

  • 使用id进行查询数据库,将查询得到的结果放置到session一级缓存中,同时复制一份数据,放置到session的快照中
  • 当使用tr.commit()的时候,同时清理session的一级缓存(flush)
  • 当清理session一级缓存的时候,会使用OID判断一级缓存中对象和快照中的对象进行比对
  • 如果2个对象(一级缓存的对象和快照的对象)中的属性发生变化,则执行update语句,此时更新数据库,更新成一级缓存中的数据
  • 如果2个对象中的属性不发生变化,此时不执行update语句

目的:确保和数据库中的数据一致

清空一级缓存

  • clear():清空所有缓存
  • evict(obj):清空一个对象

事务管理

一、事务

  • 逻辑上的一组操作
  • 要么全都成功,要么全都失败

二、事务特性

1. 原子性

事务不能分隔

2. 隔离性

执行一个事务时, 不应受到其它事务的干扰

  • 脏读:一个事务读取某一个事务未提交的数据
  • 不可重复读:一个事务读取取另一个事务已经提交的update数据,导致在前一个事务多次查询的结果不一样
  • 幻读:一个事务读取到别一个事务已经提交的insert数据,导致在前一个事务多次查询的结果不一样

3. 持久性

事务完成后, 数据就持久到数据库当中

4. 一致性

事务执行前后 ,数据的完整性要保持一致

三、事务的隔离级别

  • Read uncommitted

    • 所有问题都会发生
  • Read committed
    • 解决脏读问题
  • Repeatable read
    • 解决脏读和不可重复读
  • Serializable
    • 解决所有问题,效率较低

四、Hibernate设置事务的隔离级别

  • 在核心配置文件hibernate.cfg.xml当中
  • 通过数字来代表不同的隔离级别
<property name="hibernate.connection.isolation">4</property>

五、事务业务层连接

在业务层使用事务时,必须得要保证获取事物的连接和dao层操作的连接是同一个,否则就管理了不对应的操作

1. 使用jdbc当中事务业务层处理方法

(1)向下传递

就开始在业务层先创建好一个连接,传给dao层,让dao层使用这个连接执行操作

(2)使用ThreadLocal对象

在service方法当中把创建的连接绑定到对应的threadLocal当中,在dao方法当中,通过当前的线程获得连接对象

2. hibernate当中处理方法

  • Hibernate框架,内部已经绑定好了ThreadLocal
  • 在SessionFactory中,提供了一个方法,getCurrentSession() 方法,获取当前线程中的session
  • 此方法默认不能用,要通过配置完成
  • 在核心配置文件(hibernate.cfg.xml)当中配置
<property name="current_session_context_class">thread</property>
  • 创建一个session绑定到当前线程
  • 通过它来操作时, 不需要 close,执行结束后, 会自动的close()

原文地址:https://www.cnblogs.com/xzh0717/p/10806827.html

时间: 2024-10-11 21:06:13

Hibernate 生成策略和缓存策略的相关文章

三大框架 之 Hibernate生成策略与缓存策略(主键生成策略、持久化、持久化类划分、一级缓存、事物管理)

目录 Hibernate生成策略与缓存策略 主键生成策略 主键分类 主键的生成策略 持久化 什么是持久化 什么是持久化类 持久化类编写规则 持久化类的划分 三种状态区分 持久态对象特征 一级缓存 什么是缓存 一级缓存 一级缓存特点 一级缓存内部结构 事务管理 什么是事务 事务特性 事务的隔离级别 Hibernate设置事务的隔离级别 事务业务层连接 Hibernate生成策略与缓存策略 主键生成策略 主键分类 自然主键 主键本身就是表中的一个字段 实体中一个具体的属性,对象本身唯一的特性 创建一

基于Alluxio内存文件系统的缓存策略

Alluxio是一种基于内存的分布式文件系统,支持不同的缓存替换策略,来替换内存中的文件快.Alluxio中的文件时以文件块形式组织,其中文件通过自己实现的inode数据结构记录文件属性并索引. 下面首先介绍几种不同的缓存策略,这些缓存策略被广泛的应用在web,数据库,文件系统中. 1 基于访问频率的缓存策略 这种缓存策略是根据缓存单位的(在Alluxio中是文件块Block)访问频率来进行缓存调度,最常用的策略是LFU(Least Frequently Used)策略.该策略每次淘汰访问频率最

Hibernate(四)——缓存策略+lazy

Hibernate作为和数据库数据打交道的框架,自然会设计到操作数据的效率问题,而对于一些频繁操作的数据,缓存策略就是提高其性能一种重要手段,而Hibernate框架是支持缓存的,而且支持一级和二级两种缓存,合理的使用缓存策略可以大大提高我们的操作数据效率,但是利用不能,可能会造成不必要的麻烦.  一,一级缓存(Session缓存):  Session缓存表示将查询结果放置到Session的临时存储空间(一级缓存中).Hibernate框架默认支持一级缓存的.一级缓存的范围较小,一旦Sessio

对Hibernate缓存策略的理解和应用

引自:http://www.blogjava.net/frostwood/archive/2010/01/06/308465.html Hibernate提供了三个级别的缓存策略:Session缓存(基本的事务级缓存),Query Cache(查询缓存),Seond-Level Cache(二级缓存) Session缓存(First-Level Cache):Session是Hibernate用于管理持久化对象的核心机制,它是针对持久性数据的事务级缓存.PersistenceContext中包括

Ehcache 实现 Hibernate 二级缓存策略

1.条件查询的时候,总是发出一条select * from table_name where ....  (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象. 2.把获得的所有数据对象根据ID放入到第二级缓存中. 3.当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查:查不到,如果配置了二级缓存,那么从二级缓存中查:查不到,再查询数据库,把结果按照ID放入到缓存. 4.删除.更新.增加数据的时候,同时更新缓存. Hibernate的二级缓存策略,是针

Hibernate的二级缓存策略

Hibernate的二级缓存策略的一般过程如下: 1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象. 2) 把获得的所有数据对象根据ID放入到第二级缓存中. 3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查:查不到,如果配置了二级缓存,那么从二级缓存中查:查不到,再查询数据库,把结果按照ID放入到缓存. 4) 删除.更新.增加数据的时候,同

Hibernate的强制加载策略

推迟加载: 推迟加载机制是号码大全为了防止一些无谓的功用开支而提出来关键词挖掘工具的,所谓推迟加载即是当在真实需求数据的时分,才真实履行数据加载操作.在Hibernate中供给了对实体方针的推迟加载以及对调集的推迟加载,另外在Hibernate3中还供给了对特点的推迟加载.下面咱们就别离介绍这些品种的推迟加载的细节. A.实体方针的推迟加载: 假如想对实体方针运用推迟加载,有必要要在实体的映射装备文件中进行相应的装备,如下所示: ? …… 经过将class的lazy特点设置为true,来敞开实体

网络图片的获取以及二级缓存策略(Volley框架+内存LruCache+磁盘DiskLruCache)

在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理,每次打开应用都去网络获取图片,那么用户可就不乐意了,这里的处理就是指今天要讲的缓存策略(缓存层分为三层:内存层,磁盘层,网络层). 关于缓存层的工作,当我们第一次打开应用获取图片时,先到网络去下载图片,然后依次存入内存缓存,磁盘缓存,当我们再一次需要用到刚才下载的这张图片时,就不需要再重复的到网络

Android 开源框架Universal-Image-Loader完全解析(二)--- 图片缓存策略详解

本篇文章继续为大家介绍Universal-Image-Loader这个开源的图片加载框架,介绍的是图片缓存策略方面的,如果大家对这个开源框架的使用还不了解,大家可以看看我之前写的一篇文章Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用,我们一般去加载大量的图片的时候,都会做缓存策略,缓存又分为内存缓存和硬盘缓存,我之前也写了几篇异步加载大量图片的文章,使用的内存缓存是LruCache这个类,LRU是Least Recently Used 近