Hibernate一级缓存session的原理和内部结构

jxwnhj0717 2009-09-11 11:37:53
感觉hibernate是越学越难,像了解一下session的内部结构是什么样的,哪位高手能指教一下:

比如get和load时,session是怎么来保存真实对象和代理对象?
update时是先从数据库中加载一条数据,然后在和要更新的对象比较,若不同,则发送update语句吗?
通过load加载上来的数据,delete时会发送select语句,但好像不会填充session中缓存,为什么?
session是通过什么来判断缓存中已经有了某个对象,对象的id?
...全文
1357 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
BenzGL550 2012-07-23
  • 打赏
  • 举报
回复
get和load的区别:
  Get:立刻加载,当执行get
  ()之后,就会发出select语句查询对应的对象。查询的数据不存在返回null。
  Load:延迟加载,执行load()之后不会发出select语句,当真正使用的时候才执行sql语句去查询数据。原理是:它产生的是一个代理对象,加载到内存。查询的数据不存在会返回代理对象,并抛出 ClassNotFoundException的异常。
jxwnhj0717 2009-09-18
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 gordonkkk 的回复:]
Session不保证你执行它api时,对应的sql语句会立即执行,但Session保证,当必要的时候,sql语句一定会被执行。
load后delete,提交事物时Session会顺序执行你的操作,就是先select再delete。
[/Quote]
load要做的事就是懒加载,delete方法需要的是id,又不是一个对象,而获取id不需要发select,这里何必要发送呢?
gordonkkk 2009-09-16
  • 打赏
  • 举报
回复
Session不保证你执行它api时,对应的sql语句会立即执行,但Session保证,当必要的时候,sql语句一定会被执行。
load后delete,提交事物时Session会顺序执行你的操作,就是先select再delete。
jxwnhj0717 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 gordonkkk 的回复:]
一般情况下,get会直接查询数据库,返回你需要的对象,当没找到对象时,返回null。
load会返回一个代理对象,当你真正用到它的时候,才查询数据库。所以当没找到对象时,抛异常。
你看到的delete时发送select,是因为load的延时性。
update方法不会发送select。你一定是用了merge方法。
update就直接用你传的pojo去update,这个pojo变为持久化对象,纳入Session的缓存管理范围。
merge才会发送select,得到一个具有相同持久化标示符的对象,纳入Session的缓存管理范围,然后把你传的pojo中的属性set进去,最后返回那个缓存中的持久态对象。
这导致update和merge有个很大的区别就是,update过的pojo,将变成持久态对象,而如果此时Session中已有相同id的持久态对象的话,update将抛异常,因为Session里,持有相同持久化标示符的对象,只能有一个。而merge过的pojo,还是个脱管态对象。如果此时Session中已有相同id的持久态对象的话,merge将不发送select语句,而直接拿这个对象来用,返回值也是它。
[/Quote]


高手!!load的延时性?能详细解释一下吗?
delete时不是只需要id吗?获取对象的id和class应该不用发sql语句的啊
gordonkkk 2009-09-16
  • 打赏
  • 举报
回复
一般情况下,get会直接查询数据库,返回你需要的对象,当没找到对象时,返回null。
load会返回一个代理对象,当你真正用到它的时候,才查询数据库。所以当没找到对象时,抛异常。
你看到的delete时发送select,是因为load的延时性。
update方法不会发送select。你一定是用了merge方法。
update就直接用你传的pojo去update,这个pojo变为持久化对象,纳入Session的缓存管理范围。
merge才会发送select,得到一个具有相同持久化标示符的对象,纳入Session的缓存管理范围,然后把你传的pojo中的属性set进去,最后返回那个缓存中的持久态对象。
这导致update和merge有个很大的区别就是,update过的pojo,将变成持久态对象,而如果此时Session中已有相同id的持久态对象的话,update将抛异常,因为Session里,持有相同持久化标示符的对象,只能有一个。而merge过的pojo,还是个脱管态对象。如果此时Session中已有相同id的持久态对象的话,merge将不发送select语句,而直接拿这个对象来用,返回值也是它。
youjianbo_han_87 2009-09-16
  • 打赏
  • 举报
回复
这个要有图看才更清楚,夏昕的 深入浅出Hibernate 上有非常详细的介绍,楼主去下下来看下。
jxwnhj0717 2009-09-15
  • 打赏
  • 举报
回复
怎么没人回答呢
ouwarmth 2009-09-12
  • 打赏
  • 举报
回复
缓存的作用主要是用来提高性能,可以简单理解成一个Map;使用缓存涉及到三个操作:把数据放入缓存,从缓存中获取数据,删除缓存中的无效数据.
一级缓存,即session级共享.使用load,get,save,update等方法时都会将对象放在一级缓存中,你可以理解成是一个容器来保存的.
一般使用update一般不会直接从数据库加载数据,因为在你第一次用save方法保存数据时,在一级缓存中已有相关记录.所以当你使用update语句更新数据时,是直接从一级缓存中获取数据的(一级如果没找到,可以会从二级去找),最后更新后再修改数据库记录.
通过load加载上来的数据,一般在一级和二级缓存中都会有记录的.所在当要查找相关记录时,hibernate会首先从一级和二级缓存中去找.
嗯,session是通过对象的id判断缓存中已经有了某个对象;但好像记得session中缓存是对象的形式.
其实hibernate缓存机制不是很难理解,只要楼主把原理弄懂,比如一级和二级缓存缓存过程中的先后顺序及其相关的方法对应的缓存级别.相信楼主很快可以掌握的.
jxwnhj0717 2009-09-12
  • 打赏
  • 举报
回复
to 1#
那些基本的我都知道,我想知道hibernate内部的调用原理

若跟踪session可以发现persistenceContext->entityEntities->map->entries->table[i],我认为这个是hibernate的缓存。当get调用时,table[i]中key为这个对象,value中同样也保存着一些属性,比如:实体信息(无id)/existsInDatabase=true/loadedState=加载上来的状态/deletedState=true,当load调用时,table为空,代理对象在哪里?

session.delete()根本就无视懒加载,hibernate作者问题?

hibernate在update时,为什么情愿先select后update,直接update不是更好,毕竟update大部分时间都是会发的。
JKhench 2009-09-12
  • 打赏
  • 举报
回复
楼上的说的很对补充下load吧
load用的延迟加载也就是lazy在查询数据库时只查主键。保持在session中。
单你要适用load出来的对象时它才会查询数据库的完整信息。

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧