hibernate随笔(知识盲点)


get与load的区别


相同点:都是根据对象的id来加载对象
不同点:当查询id不存在时,get会返回一个null,而load会抛出异常(当加载的id不存在时,get返回空值,load抛出异常)


为什么呢?

load采用的是延迟加载,get是直接加载。异常是什么时候报出来的?load采用的是代理模式,load执行完后返回的是一个代理对象,此时不会报出异常,这个代理对象没有被初始化,其中没有目标对象,当访问对象中详情的时候,会发送lelect语句返回为null也不会报错,而拿这个空值来初始化代理对象就会抛出异常,因为代理对象的目标对象不能为空。(因为在代理模式中代理对象必须要有目标对象)

extra特别懒加载能用聚合查询绝不做详情查询,聚合函数查询效率远大于详情查询效率。


session.get都做了哪些工作?
1)将数据从DB中读取出来
2)将数据转换为对象放到堆内存中
3)将对象的id放入session Map的key值,将对象的引用放入session缓存Map的value值中
4)将对象的数据(对象的详情)放入到“快照”中
当事务提交时做的工作,将堆内存中的数据与快照中的数据进行对比,若比较结果不相同,则进行update操作


执行刷新的时间点(refresh)只有一个:事务的提交
执行同步的时间点(flush)的时间点:1)Query查询操作  2)显示的调用session.flush()方法  3)事务的提交



修改刷新点:session.setFlushMode(?);FlushMode


二级缓存:
内置缓存:只读,不可修改,默认开启
外置缓存:引用第三方产品
根据缓存内容不同分为三类:1)类缓存:缓存对象为实体类对象
2)集合缓存 3)查询缓存
类缓存:缓存的是对象详情(存放在专门的一个称为实体区域的缓存中,缓存的内容为对象的详情)
集合缓存:缓存的是所有包含对象的ID(存放在一个专门称为集合区域的缓存中,缓存内容为所有包含对象的id)

Query查询缓存:其从Query缓存中查找的依据不再是查询对象的id,而是根据Query语句来的,也就是说Query查询结果存放到Query缓存中时其key为Query的查询语句,value为查询结果。根据Query语句进行匹配是否从缓存中读取数据。(不是很好用)


当使用query.executeUpdate()时会绕过一级缓存而直接更新到数据库。
之后在使用get查询修改的数据,查询到的仍然是修改之前的数据。按照之前学习的理论,这里的get查询会先查找一级缓存,结果没有,再查找二级缓存,结果是有的。但为什么没有从二级缓存中读取这个数据,而是从DB中直接查询?
因为query的executeUpdate方法,会修改二级缓存中的一个属性:updateTimestamp,修改时间戳
什么意思呢?实际上二级缓存对象中缓存的内容要比一级缓存对象中缓存的内容要多一个属性,修改时间戳。
一旦这个属性被修改,那么,查询会不从二级缓存对象中读取数据,而是直接从DB中直接读取。
使用executeUpdate进行修改操作与快照无任何关系。


事务的四大特性:1)原子性  2)一致性  3)隔离性  4)持久性
事务的并发所引出的问题:不可重复读:1)更新了数据 2)增加了数据 3)删除了数据  ;后两种现象称为幻影现象
当隔离级别设置为可重复读后,会引发幻读


隔离级别:
mysql 的默认隔离级别:4
oracle 的默认隔离级别:2


一般有业务需求的时候才会写级联关系。


悲观锁:在select语句后添加for update,则会给每一条符合条件的记录添加写锁(悲观锁不太懂)
变量命名不要用:sVersion。这样在解析的时候可能会出问题,应直接写成sversion(版本号)


hibernate用的是JPA的注解并不是hibernate自己的,所以导包的时候要导javax的包。

猜你喜欢

转载自blog.csdn.net/qq_36443497/article/details/77303448