在Session接口的实现中包含啦一系列的JAVA集合,这些JAVA集合构成了Session的缓存,也就是Hibernate的一级缓存。只要Session实例没有结束生命周期,且没有清理缓存,那么存放在Session的对象就不会结束生命周期。
作用:Session缓存可减少Hibernate应用程序访问数据库的频率。测试如下:
@Test
public void test() {
News news =(News) session.get(News.class, 1);
System.out.println(news);
News news2 =(News) session.get(News.class, 1);
System.out.println(news2);
System.out.println(news==news2);
}
关于Session 缓存的几个方法:
flush():Session按照缓存中对象的属性变化来同步更新数据库。
默认情况下Session在以下时间点刷新缓存:
–显示调用Session的flush()方法。
–当应用程序调用Transaction的commit()方法的时候,该方法先flush(),然后在向数据库提交事务。
–当应用程序执行一些查询操作,比如HQL,Criteria.如果缓存中持久化对象的属性已经发生啦变化,会先flush缓存,以保证查询结果能够反映持久化对象的最新状态。
flush缓存的例外情况:如果对象使用native生成器生成OID,那么当调用Session的save()方法时,会立即执行插入语句。因为save方法后,必须1保证该对象的ID是存在的!但此时也只是存在于缓存中,数据库中没有数据。
commit()和flush()方法的区别:commit是相对Hibernate事物而言的,commit()执行时会先调用flush()方法,然后提交事物。提交以后就意味着对数据库的操作永久保存下来。flush()是执行一系列的sql语句,但不会提交事物。
refresh():Session中存在一级缓存,当设置啦该属性的时候,当进行两次相同的查询时,数据库中的数据发生啦改变,不使用缓存,而是重新发送sql进行查询。当然啦,mysql的默认事物隔离级别是REPEATABLE READ,要修改成READ COMMITTED。代码如下
@Test
public void test() {
News news =(News) session.get(News.class, 1);
System.out.println(news);
session.refresh(news);
System.out.println(news);
}
配置中加
<!-- 配置Hibernate的事物隔离级别 -->
<property name="connection.isolation">2</property>
至于事物的四种隔离级别,不在这里阐述。
运行的结果
个人理解:flush()主要是Hibernate代码中数据发生了变化,不提交但要和从数据库中取到的放在缓存中的数据保存一致。而refresh()主要是执行代码时,数据库的数据发生啦变化,这时候不能够再取缓存的数据,需要重新发sql取数据。对比如如下:
clear():主要将Session中的缓存清理掉,比较容易理解,这里不做过多的解释。