首页 新闻 会员 周边

hibernate二级缓存问题,取了缓存却非同一个对象

0
悬赏园豆:30 [待解决问题]
 1 @Test
 2     public void testCache() {
 3         Session session = sf.openSession();
 4         session.beginTransaction();
 5         Topic t1 = (Topic)session.get(Topic.class, 5);
 6         Topic t3 = (Topic)session.get(Topic.class, 5);
 7         System.out.println("session1:");
 8         System.out.println(t1);
 9         System.out.println(t3);
10         session.getTransaction().commit();
11         session.close();
12         
13         
14         
15         Session session2 = sf.openSession();
16         session2.beginTransaction();
17         Topic t2 = (Topic)session2.load(Topic.class, 5);
18 //        sf.evict(Topic.class, 5);
19         System.out.println("session2:");
20         System.out.println(t2);
21         session2.getTransaction().commit();
22         session2.close();
23     }

console:

Hibernate:
select
topic0_.id as id2_1_,
topic0_.category_id as category4_2_1_,
topic0_.createDate as createDate2_1_,
topic0_.title as title2_1_,
category1_.id as id0_0_,
category1_.name as name0_0_
from
Topic topic0_
left outer join
Category category1_
on topic0_.category_id=category1_.id
where
topic0_.id=?

session1:

com.bjsxt.hibernate.Topic@1056bc5:5
com.bjsxt.hibernate.Topic@1056bc5:5
session2:
com.bjsxt.hibernate.Topic@f26800:5

 

我的问题:

session2里面load时没有发sql就证明是从二级缓存里取的啊,但为啥拿出的topic对象与之前在session1里的不是同一个呢?

senlinmu的主页 senlinmu | 初学一级 | 园豆:172
提问于:2013-03-15 09:57
< >
分享
所有回答(1)
0

 其实二级缓存在存储数据的时候,做了一些特殊的处理,当数据从数据库加载到内存的时候,放入一级缓存(之前一级缓存的原理就不细说了),也罢数据放入二级缓存了,但是放入二级缓存的数据却不是对象,这一点和一级缓存有区别,一级缓存放入的是一个具体的对象,对象的属性是有值的,所以可以直接获取(并且是同一个对象),但数据哎放入二级缓存的时候,hibernate内部吧该对象装箱了(吧具体对象转化成了object对象),但该object对象依然具有和和原始对象一样的属性只不过类型却是object类型(也称散装数据),装箱的同时也把该对象的类型字符串(包名加类型)也保存了一份,具体结构是,吧该对象和该对象的类型字符串通过键值对保存了二级缓存(本质是一个map集合所以可以通过键值对保存),但键却很特殊的字符串,键是该类型字符串和该对象的oid(对呀数据主键)的拼接,通过”#”分割,具体是类字符串#oid,对应该对象(objec)。当重二级缓存中获取该数据(不能说是对象)的时候,会更具id和类字符去匹配二级缓存的所有key,如果能找到,则通过反射生产一个对象,并返回给用户(程序),这就很合理的解释了为什么不是同一个对象,因为是反射生产的,和很好的解释了为什么要保存该对象的类字符串,那么为什么要反射,而不直接吧该对象拆箱呢?,个人认为:如果拆箱(吧object转化为具体的po对象)就是一个对象,二级缓存是多个线程共享,如果多个用户同时公用同一个对象(内存地址的指向相同),会引发安全问题(反正这样不好),

巴黎的雨季 | 园豆:198 (初学一级) | 2016-08-14 17:44
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册