[TOC]
前言
说起来挺丢人的,工作也快一年了,还没有好好看过几乎天天接触的Hibernate。昨天在开发的时候又遇到了与对象状态和缓存有关的问题,于是找了两篇博客看了看,解决了问题,简单记录一下。
然后。。我用wordpress新搭的博客,欢迎访问:http://blog.fjhdtp.cn/;
教程链接http://www.jianshu.com/p/56750622cac9。
Hibernate的两层缓存机制
Hibernate有两层缓存机制,第一级是Session的缓存,第二级是SessionFactory的缓存。
Session的缓存不能被卸载,并且是事务范围的缓存(通常一个Session对应一个事务),这也是为什么懒加载需要在session关闭之前(session绑定在ThreadLocal)。
SessionFactory对象的生命周期和应用程序的过程相对应,因此SessionFactory的缓存是进程或集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。
Hibernate执行查找的过程
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;
查不到,如果配置了二级缓存,那么从二级缓存中查;
如果都查不到,再查询数据库,把结果按照ID放入到缓存删除、更新、增加数据的时候,同时更新缓存。
Hibernate对象的三种状态
Hibernate的对象有三种状态:transient(临时)、persistent(持久)、detached(脱管)。
- 临时态(transient) 临时态的对象没有被Hibernate的缓存所管理,并且在数据库中没有与之相对应的数据。
- 持久态(persistent) 持久态的对象被Hibernate的缓存所管理,并且在数据库中有与之对应的数据。
- 脱管态(detached) 脱管态的对象脱离了Hibernate的缓存管理,并且在数据库中有与之对应的数据。
遇到的问题
我有一个Table A, 我从前台获取一些数据,放入对象b中, 如果A中有对应的数据, 则update()
,如果没有则save()
。结果我在程序中获得了持久态的对象a(当然a、b都是同一个类的对象)后,试图将a的OID赋值给b,然后update()
脱管态的b,结果就报错了。
之后我试图使用merge()
来解决这个问题,结果每次都会新增一条数据。
稍稍研究了下,只要把临时态对象的数据拷贝到持久态对象中,然后保存持久态对象就可以了。