问题描述
第一次提问,希望有人能帮忙解答.有一个B/S系统用hibernate做.有一个session A只做查询操作,另一个session B做插入操作.如果我先在session A中查询一系统对象.为了下次查询速度更快,我不做session A的清理.然后session B中新增几条记录,那么session A中如果查询出由session B新增的几条记录呢?
解决方案
Hibernate中的缓存分两种:一级缓存(Session级别)和二级缓存(SessionFactory级别) 这里说一下一级缓存的用法。 每一个Session实例都可以看作一个容器,无论何时,当给save(),update()等方法传递一个对象时,或用load(),get()等方法获得一个对象时,该对象都将被加入到Session的内部缓存中。每一个持久化的对象,都必然位于Session缓存中,这个缓存里存放着当前Session范围内的持久对象,当应用程序需要使用对象的时候,就会先从当前的Session缓存中获取对象,如果获取不到,再直接发送SQL语句到数据库中查询,将记录的字段值组装成对象后放到Session中,以供应用程序调用。 其实简单总结一下其实Session的作用就是:在数据库和应用程序之前充当一个中间容器,减少程序访问数据库的次数。很多对象数据不是经常改变的,第一次访问这个对象时,Hibernate就将这个对象放到Session里面,以后只要这个对象没有改动过,应用程序再访问这个对象时,Hibernate就不会去数据库中查找它的数据,而是从内存中直接返回应用程序,这样做当然效率要比没有Session高得多。 于是,在这里有一个问题:如果应用程序访问一个对象,并对这个对象的数据进行操作改变了它的某些字段值,而这个操作必然是提交到了数据库的,但是缓存内的数据却仍然是未改变之前的那些数据,那么下次应用程序访问这个对象的时候岂不就得到的是缓存内的错误数据而非数据库中的真实数据? 这里就涉及到了一个清理缓存的概念,清理缓存是指查看缓存中的数据与数据库是否同步,如果缓存数据与数据库不一样,则发送更新语句把缓存数据与数据库同步;如果一样,则不操作。也就是说,只需要在适当的时候调用session.flush()清理一下缓存就可以了。什么才是适当的时候呢,在一个session中,有两个不同的清理点,如下代码片段: ..............//打开session,开启事务 //code segment1 //code segment2 //清理点1:这里经常是在查询语句之前改变了对象的属性值(AUTO,ALWAYS) //code segment3 //清理点2:提交事务的时候调用flush()清理缓存(COMMIT) ........//提交事务,关闭session 其实在一个事务中,对数据进行操作使其改变了值,这种变换不会立即提交到数据库。因为有可能一个对象的某个属性发生了好几次变化(如某用户连续改了好几次自己的密码),在这样的情况下,Hibernate能把一些数据改变作一下结合,并对数据库进行最小数量的请求,它只向数据库发送一条update语句就可以把这些数据变化都包括了,当然这些都归功于session的缓存。(说到这里我就顺便发一句牢骚,特讨Hibernate生成的那一堆又臭又长的SQL语句,虽然每次我都设置的show_sql,但我极少去看那些SQL语句。) PS: 上面代码片段里的AUTO,ALWAYS,COMMIT是flush模式,这里先不写吧,下次写了。太晚了,还是睡觉去咯,其实觉得学习最重要的还是要理清楚概念,今天我看这个session就是因为以前学hibernate的时候没有把各种概念搞得很清楚,以至于现在回头去补习相关概念........哭~~~~~