Hibernate学习③
一、对象状态
1、临时状态(陌生人借钱)
2、持久状态(好朋友借钱)
3、游离状态(昔日好友,同学借钱)
说明:
①hibernate是通过管理对象【持久化对象】来操作数据。
②hibernate中的三种状态对象是可以相互转换的,通常编码时只关注持久化对象。关注get、save、update方法操作后的对象
二、一级缓存、快照(orm特性)
· 所谓一级缓存其实就是session级别的缓存
1、用户第一次访问数据。拿到一条数据,它将数据形成一个快照保存到session会话中, 并且利用反射机制将值封装进实体类中
2、当封装好的持久化对象里面的属性值发生改变时,它会与session中的快照进行对比。如果不一致,就会进行修改更新
三、加载策略
1、分类
①立即加载
不管生什么时候用,用不用,都会生成Sql语句操作数据库 ------性能较差
②延迟加载(懒加载)
懒加载的策略【什么时候用,什么时候生成调用 ---------优化性能】:
①在调用session会话的数据库操作方式时,并不会直接生成sql语句操作数据库。而是先创建一个代理对象,将oid(object id1)存放session的代理对象中。
②当具体的要用到持久化对象的时候,才会生成sql语句进行查询
说明:
* 明星、经纪人 -——>接活动
* 经纪人接了活动,干事的明星
* 明星生病了 session
* 经纪人 代理
拓展:
1、单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点
2、优点:①实例控制 ②灵活性
3、模式:
(1)饱汉模式
(2)饿汉模式/懒汉模式(线程不安全)
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
说明:
1、单例模式 只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等
2、 单例的缺点 就是不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
四、并发控制 version
1、说明: 在产品上线时发现当用户数量大并发性能差,经常发现数据库死锁,经诊断,是由于设置了不正确的事务隔离
2、JTA具有的3个接口:
①UserTransaction接口 :执行事务划分和基本的事务操作
②TransactionManager接口 :执行上下文管理
③Transaction接口 :在一个具有多个数据库的系统中,可能一个程序将会调用几个数据库中的数据,
需要一种分布事务,或者准备用JTA来管理Session的长事务
3、选择隔离级别:
数据库系统提供了四种事务隔离级别供用户选择。
① Serializable(隔离级别值:8):串行化。隔离级别最高
②Repeatable Read(4):可重复读。
③Read Committed(2):读已提交数据。
④ Read Uncommitted(1):读未提交数据。隔离级别最差(不建议使用,除非只做查询)。
********优先考虑Read Committed,它能够避免脏读,而且具有较好的并发性能**********
在hibernate.cfg.xml中设置隔离级别:
<session-factory>
<property name="hibernate.connection.isolation">2</property>
</session-factory>
当数据库系统采用Red Committed隔离级别时,会导致不可重复读和第二类丢失更新的并发问题
4、解决:
(1)乐观锁:唯一能够同时保持高并发和高可伸缩性 版本检查使用版本号、 或者时间戳来检测更新冲突(并且防止更新丢失)
(2)在数据库表中加入一个version(版本)字段,在读取数据时连同版本号一起读取,并在更新数据时比较版本号与数据库表中的版本号,如果等于数据库表中的版本号则予以更新,并递增版本号,如果小于数据库表中的版本号就抛出异常。
(3)悲观锁:为了避免当前事务的操作受到干扰,先锁定资源【影响并发性能,谨慎使用】