一级缓存:
Hibernate的一级缓存是指Session(属于事务范围的缓存,由Hibernate管理,无需干预)
它是一块内存空间,用来存放从数据库查询出的java对象,有了一级缓存,应用程序可以减少访问数据库的次数,提高了性能
在使用Hibernate查询对象的时候,首先会使用对象属性的OID值(对应表中的主键)在Hibernate的一级缓存进行查找
如果找到,则取出返回,不会再查询数据库
如果没有找到,再到数据库中进行查询操作。然后将查询结果存放到Session一级缓存中
Test:
//第一次查询(会查询数据库) Customer c1 = session.get(Customer.class, 15); System.out.println(c1); //第二次查询(不会查询数据库) Customer c2 = session.get(Customer.class, 15); System.out.println(c2);
tx.commit(); session.close();
Console:
Hibernate: select customer0_.c_id as c_id1_0_0_, customer0_.c_name as c_name2_0_0_, customer0_.c_gender as c_gender3_0_0_, customer0_.c_age as c_age4_0_0_, customer0_.c_level as c_level5_0_0_ from t_customer customer0_ where customer0_.c_id=? com.roxy.hibernate.pojo.Customer@31c269fd com.roxy.hibernate.pojo.Customer@31c269fd
----- 只执行一次SQL语句
Test2:测试一级缓存的范围
//第一次查询(会查询数据库) Session session1 = HibernateUtil.openSession(); Transaction tx1 = session1.beginTransaction(); Customer c1 = session1.get(Customer.class, 15); System.out.println(c1); tx1.commit(); session1.close(); //第二次查询(会查询数据库) Session session2 = HibernateUtil.openSession(); Transaction tx2 = session2.beginTransaction(); Customer c2 = session2.get(Customer.class, 15); System.out.println(c2); tx2.commit(); session2.close();
Console:
Hibernate: select customer0_.c_id as c_id1_0_0_, customer0_.c_name as c_name2_0_0_, customer0_.c_gender as c_gender3_0_0_, customer0_.c_age as c_age4_0_0_, customer0_.c_level as c_level5_0_0_ from t_customer customer0_ where customer0_.c_id=? com.roxy.hibernate.pojo.Customer@31c269fd Hibernate: select customer0_.c_id as c_id1_0_0_, customer0_.c_name as c_name2_0_0_, customer0_.c_gender as c_gender3_0_0_, customer0_.c_age as c_age4_0_0_, customer0_.c_level as c_level5_0_0_ from t_customer customer0_ where customer0_.c_id=? com.roxy.hibernate.pojo.Customer@4593ff34
----- 执行两次SQL查询,说明一级缓存的作用范围是session
快照机制:
当执行commit()时,Hibernate同时会清理session的一级缓存(flush),也就是将堆内存中的数据与快照中的数据进行对比,如果不一致,会执行同步操作(update)操作,如果一致,则不执行update
只有持久化对象能走快照机制
快照是数据的副本
快照属于一级缓存
快照是在堆内存中的
快照的作用:保证数据的一致性
Test:
Customer c1 = session.get(Customer.class, 15); c1.setName("harry"); tx.commit(); session.close();
Console:
Hibernate: select customer0_.c_id as c_id1_0_0_, customer0_.c_name as c_name2_0_0_, customer0_.c_gender as c_gender3_0_0_, customer0_.c_age as c_age4_0_0_, customer0_.c_level as c_level5_0_0_ from t_customer customer0_ where customer0_.c_id=? Hibernate: update t_customer set c_name=?, c_gender=?, c_age=?, c_level=? where c_id=?
----- 自动执行update方法
一级缓存管理:
如果对象不在一级缓存中,无法进行对比,数据库不能自动更新
一级缓存默认开启,无法关闭,只能清空(evict | clear | close),持久态转化为游离态
evict:清除一级缓存中某个对象
clear:清除一级缓存所有对象
close:关闭Session,清除一级缓存
Test:
Session session = HibernateUtil.openSession(); Transaction tx = session.beginTransaction(); //查询 Customer c1 = session.get(Customer.class, 16); c1.setName("draco"); //session.evict(c1); session.clear(); tx.commit(); session.close();
Console:
select customer0_.c_id as c_id1_0_0_, customer0_.c_name as c_name2_0_0_, customer0_.c_gender as c_gender3_0_0_, customer0_.c_age as c_age4_0_0_, customer0_.c_level as c_level5_0_0_ from t_customer customer0_ where customer0_.c_id=?
----- 只执行select,没有自动更新
其他操作:
flush:
修改一级缓存,针对内存操作,在session执行flush操作时,将缓存变化同布在数据库
refresh:
重新查询数据库,更新快照和一级缓存
Session手动控制缓存:
Always:每次查询时,session都会flush,即自动更新
Auto:在某些查询时,session会默认flush,例如commit
Commit:在事务提交时
Manual:只有手动提交事务才会同步到数据库
参考链接:http://blog.csdn.net/luckyzhoustar/article/details/47665495