标签:无法创建 编写 级别 flush ati nfa 调用 red 数据
目录
自然主键
主键本身就是表中的一个字段
实体中一个具体的属性,对象本身唯一的特性
创建一个学生表
姓名
年龄
身份证号(主键)
代理主键
主键本身不是表中必须的一个字段
创建一个学生表
姓名
年龄
身份证号
SID
这样的主键代理主键
在实际开发当中尽量要使用代理主键
设计以学生身份证号为主键
在业务上添加学生身份证号,不小心录入错误
主键修改是如果两个相同是允许修改的。所以一旦参于业务,就可能存在一些问题
主键一般只作为条件,查询,不参与修改,使用代理主键就和表当中的业务信息没有关系
开发中为什么要使用代理主键
一旦自然主键参与到业务逻辑当中,后期有可能修改源代码
一个好的程序设计要满足开闭原则(Open Closed Principle)
对程序的扩展是open开放的
对修改源码是close的
oracle
mysql
jdbc
只改配置文件就行
increment
自动增加策略
long
short
int
原理
在单线程中使用,不要在多线程中使用
两个线程同时对数据库当中的id字段查询
两个人查询的内容都是1
其中一个肯定会报错
先先发送一条语句
select max(id) from 表
然后让id加1
identity
自动增长
原理
使用是数据库底层的增长策略
适用于有自动增长机制的数据库
Mysql有自动增长
Oracle是没有自动增长的,是通过序列来完成这种效果的
sequence
自动增长
原理
采用序列的方式
必须得要支持序列
Oracle支持序列
Mysql不支持序列
uuid
适用于字符串类型的主键
使用hibernate中随机生成字符串的主键
native
本地策略
在identity和sequence自动切换
assigned
hibernate不会帮你管理主键
需要自己手动调用或通过程序来去生成主键
1.对持久化类提供一个无参的构造方法
底层会通过反射创建对象
如果没有无参构造,反射是无法创建对象的
一般,类自带“看不见”的持久化类
2.对内部私有的字段要提供get与set方法
不提供的话。hibernate就无法获取对象的值
3.对象持久化类提供一个OID与数据库表当中的主键对应
Java中通过对象的地址来区别是否为同一个对象
数据库中通过主键来区别是否是同一条记录
Hibernate中通过持久化类的OID属性来区分是否是同一个对象
4.持久化类中的属性尽量使用包装类型
包装类型的默认值为NULL
基本数据类型的默认值为数字
5.持久化类不要使用final修饰
跟延时加载有关系
延时加载是Hibernate优化的手段
返回的是一个代理对象
使用动态代理
低层使用的是字节码增强技术,继承这个类来进行代理
如果使用了final,就不能被继承
不能被继承,代理对象就无法创建,延时加载就无效了
瞬时态
没有唯一的OID
没有被session管理
这种对象我们称为瞬时态对象
持久态
有唯一的OID
有被session管理
这种对象我们称为持久态对象
游离态/托管态/离线态
有唯一的OID
没有被session管理
?
瞬时态
刚new出对象时,还没有设置id,还没有被session所管理
持久态
已经有了id
调用session方法,把对象给session,才被session所管理
添加到session之后, 对象一直处理持久态
当对象处于持久态时, 可以自动更新数据库
游离态
把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)
? 清空一个对象
原子性
事务不能分隔
隔离性
执行一个事务时, 不应受到其它事务的干扰
脏读
一个事务读取某一个事务未提交的数据
不可重复读
一个事务读取取另一个事务已经提交的update数据,导致在前一个事务多次查询的结果不一样
幻读
一个事务读取到别一个事务已经提交的insert数据,导致在前一个事务多次查询的结果不一样
持久性
事务完成后, 数据就持久到数据库当中
一致性
事务执行前后 ,数据的完整性要保持一致
Read uncommitted
所有问题都会发生
Read committed
解决脏读问题
Repeatable read
解决脏读和不可重复读
Serializable
解决所有问题,效率较
低
? 在核心配置文件hibernate.cfg.xml当中
? 通过数字来代表不同的隔离级别
?
<property name="hibernate.connection.isolation">4</property>
在业务层使用事务时,必须得要保证获取事物的连接和dao层操作的连接是同一个,否则就管理了不对应的操作
向下传递
就开始在业务层先创建好一个连接,传给dao层,让dao层使用这个连接执行操作
使用ThreadLocal对象
在service方法当中把创建的连接绑定到对应的threadLocal当中
在dao方法当中,通过当前的线程获得连接对象
Hibernate框架,内部已经绑定好了ThreadLocal
在SessionFactory中,提供了一个方法,getCurrentSession()方法
获取当前线程中的session
此方法默认不能用
通过配置完成
在核心配置文件当中配置
<property name="current_session_context_class">thread</property>
创建一个session绑定到当前线程
通过它来操作时, 不需要 close,执行结束后, 会自动的close()
三大框架 之 Hibernate生成策略与缓存策略(主键生成策略、持久化、持久化类划分、一级缓存、事物管理)
标签:无法创建 编写 级别 flush ati nfa 调用 red 数据
原文地址:https://www.cnblogs.com/mumuyinxin/p/10708263.html