一级缓存
为什么要用缓存?
目的:减少对数据库的访问次数!从而提升hibernate的执行效率!
Hibernate中缓存分类:
一级缓存
二级缓存
概念
1)Hibenate中一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数! 只在session范围有效! Session关闭,一级缓存失效!
2)当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session的缓存中。
3)Session的缓存由hibernate维护,用户不能操作缓存内容; 如果想操作缓存内容,必须通过hibernate提供的evit/clear方法操作。
特点:
只在(当前)session范围有效,作用时间短,效果不是特别明显!
在短时间内多次操作数据库,效果比较明显!
缓存相关几个方法的作用
session.flush(); 让一级缓存与数据库同步
session.evict(arg0); 清空一级缓存中指定的对象
session.clear(); 清空一级缓存中缓存的所有对象
在什么情况用上面方法?
批量操作使用使用:
Session.flush(); // 先与数据库同步
Session.clear(); // 再清空一级缓存内容
面试题1: 不同的session是否会共享缓存数据?
不会。
User1 u1 = Session1.get(User.class,1); 把u1对象放入session1的缓存
Session2.update(u1); 把u1放入session2的缓存
U1.setName(‘newName’);
如果生成2条update sql, 说明不同的session使用不同的缓存区,不能共享。
面试题2: list与iterator查询的区别?
list()
一次把所有的记录都查询出来,
会放入缓存,但不会从缓存中获取数据
Iterator
N+1查询; N表示所有的记录总数
即会先发送一条语句查询所有记录的主键(1),
再根据每一个主键再去数据库查询(N)!
会放入缓存,也会从缓存中取数据!
测试一级缓存:
JavaBean User:
<span style="font-family:Courier New;font-size:14px;">package cn.itcast.cache; public class User { private int userId; private String userName; public int getUserId() { return userId; } public void setUserId(int useId) { this.userId = useId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Override public String toString() { return "User [useId=" + userId + ", userName=" + userName + "]"; } } </span>
Uer.hbm.xml文件
<span style="font-family:Courier New;font-size:14px;"><?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.itcast.cache" auto-import="true"> <class name="User" table="t_user"> <id name="userId"> <generator class="native"></generator> </id> <property name="userName" column="userName"></property> </class> </hibernate-mapping></span>
1.数据库中保存数据:
<span style="font-family:Courier New;font-size:14px;">@Test public void test(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); User user =new User(); user.setUserName("翁宗顺"); session.save(user); transaction.commit(); session.close(); }</span>
2.数据库中多次查询数据
<span style="font-family:Courier New;font-size:14px;">@Test public void testGet(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); User user=null; user=(User) session.get(User.class, 1);//第一才会从一级缓存中查找数据,如果没有就从数据库查找 // session.evict(user);//清除缓存中指定的数据 user=(User) session.get(User.class, 1);//因为一级缓存中已经有了数据,所以直接从一级缓存中 查找数据即可 transaction.commit(); session.close(); }</span>
测试发现如果两次查询数据一样,那么第一次会把数据放到一级缓存中,第二次查询的时候直接从缓存中取出数据.这样就极大的提高了效率.可以发现控制台只打印一条sql数据.
如果使用session.evict(user):清除缓存中指定的对象 session.clear()清除缓存中所有的数据.第一次会从数据库中查询 第二次查询的时候会从缓存中找数据,但是缓存已经被清空 因此就会从数据库中查找数据.可以发现控制台打印两条sql语句
3.测试缓存是否可以跨session获取
<span style="font-family:Courier New;font-size:14px;">@Test public void testUpdate(){ Session session1 = HibernateUtil.getSession(); Transaction transaction1 = session1.beginTransaction(); Session session2 = HibernateUtil.getSession(); Transaction transaction2 = session2.beginTransaction(); User user=null; user=(User) session1.get(User.class, 1); //这说明只是在自己的session范围内有效 user=(User) session2.get(User.class, 1); transaction1.commit(); session1.close(); transaction2.commit(); session2.close(); }</span>
测试发现:控制台打印两条sql语句 这说明 只在(当前)session范围有效,作用时间短,效果不是特别明显!
4.测试集合数据中的缓存
list遍历
//测试list:一次性把 所有的记录都查询出来 @Test public void testList(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from User"); List<User> list = q.list(); for(User u:list){ System.out.println(u.getUserName()); } transaction.commit(); session.close(); }
测试:控制台打印一条sql语句,即一次性查询出所有的数据
iterate遍历
/测试iterate:它是N+1方式的查询 // 即先发送一条语句查询所有记录的主键 //然后根据每一个主键再去数据库中查询(N) @Test public void testIterate(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from User"); Iterator it = q.iterate(); while(it.hasNext()){ User u=(User) it.next(); System.out.println(u.getUserName()); } transaction.commit(); session.close(); }
测试:先发送一条语句查询所有记录的主键,然后根据每个主键去数据库中查询
iterate缓存
@Test public void cacheIterate(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from User"); Iterator it = q.iterate(); while(it.hasNext()){ User u=(User) it.next(); System.out.println(u.getUserName()); } System.out.println("============"); it = q.iterate(); while(it.hasNext()){ User u=(User) it.next(); System.out.println(u.getUserName()); } transaction.commit(); session.close(); } @Test public void cacheList(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from User"); List<User> list = q.list(); for(User u:list){ System.out.println(u.getUserName()); } System.out.println("=============="); list = q.list(); for(User u:list){ System.out.println(u.getUserName()); } transaction.commit(); session.close(); }
测试:iterate会把数据保存到一级缓存,也可以从一级缓存中获取数据
list缓存 :
@Test public void cacheList(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from User"); List<User> list = q.list(); for(User u:list){ System.out.println(u.getUserName()); } System.out.println("=============="); list = q.list(); for(User u:list){ System.out.println(u.getUserName()); } transaction.commit(); session.close(); }
测试 :通过测试我们不能判断list遍历的方式是否把数据放到了一级缓存中,也不能判断能否从一级缓存中取出数据
先使用list 再使用iterate
@Test public void cacheList2(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from User"); List<User> list = q.list(); for(User u:list){ System.out.println(u.getUserName()); } System.out.println("=============="); Iterator it = q.iterate(); while(it.hasNext()){ User u=(User) it.next(); System.out.println(u.getUserName()); } transaction.commit(); session.close(); }
测试:list遍历可以把数据保存到一级缓存中,但是不能从一级缓存中取出数据
版权声明:本文为博主原创文章,未经博主允许不得转载。