缓存不止存在与程序中,电脑硬件乃至于生活中都存在缓存
目的:提高效率
比如IO流读写字节,如果没有缓存,读一字节写一字节,效率低下
hibernate中的一级缓存:提高操作数据库的效率
示例:
抽取的工具类
package utils;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;public class HibernateUtils { ???private static SessionFactory sf; ???????static{ ???????//1 创建,调用空参构造 ???????Configuration conf = new Configuration().configure(); ???????//2 根据配置信息,创建 SessionFactory对象 ????????sf = conf.buildSessionFactory(); ???} ???????//获得session => 获得全新session ???public static Session openSession(){ ???????????????//3 获得session ???????????????Session session = sf.openSession(); ???????????????????????????????return session; ???????????} ???//获得session => 获得与线程绑定的session ???public static Session getCurrentSession(){ ???????//3 获得session ???????Session session = sf.getCurrentSession(); ???????????????return session; ???} ???}
测试类:
示例1:
package cache;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.junit.Test;import domain.Customer;import utils.HibernateUtils;//测试一级缓存public class Demo { ???@Test ???//证明一级缓存存在 ???public void fun1(){ ???????//1 获得session ???????Session session = HibernateUtils.openSession(); ???????//2 控制事务 ???????Transaction tx = session.beginTransaction(); ???????//3执行操作 ???????????????Customer c1 = session.get(Customer.class, 1l); ???????Customer c2 = session.get(Customer.class, 1l); ???????Customer c3 = session.get(Customer.class, 1l); ???????Customer c4 = session.get(Customer.class, 1l); ???????Customer c5 = session.get(Customer.class, 1l); ???????????????System.out.println(c3==c5);//true ???????//4提交事务.关闭资源 ???????tx.commit(); ???????session.close();// 游离|托管 状态, 有id , 没有关联 ???????????????????????//结果(保证数据库中存在主键为1的数据): ???????//这里调用了五次方法,但是只打印一次SQL语句 ???}}
原理:程序第一次调用get方法,hibernate发送SQL语句查询数据库,查询结果以ResulySet对象返回,
hibernate再组装成Customer(实体类对象),存入session缓存对象,对象返回给程序
第二次调用get方法,会先从缓存中查看是否存在id=1的Customer对象,如果有,直接返回缓存中的对象
多次调用原理相同
明显地发现:这里的缓存技术很好地提升了效率
示例2:
???@Test ???// ???public void fun2(){ ???????//1 获得session ???????Session session = HibernateUtils.openSession(); ???????//2 控制事务 ???????Transaction tx = session.beginTransaction(); ???????//3执行操作 ???????????????Customer c1 = session.get(Customer.class, 1l); ???????????????c1.setCust_name("哈哈");//4提交事务.关闭资源 ???????tx.commit(); ???????session.close();// 游离|托管 状态, 有id , 没有关联 ???????????????????}
引入了快照的概念
原理:
上边的原理其实有省略,数据库返回结果后,hibernate组装的时候,其实组装了两个对象,
一个放入缓存中,一个放入快照,返回给程序的是缓存对象,程序第一次修改了缓存对象,事务提交,
这时候hibernate比较缓存中的对象和快照,如果有变化,会同步到数据库中,没有变化,什么都不做
这里就提高了效率,不会多次去数据库查询,只需要比对缓存中的对象,减少不必要地SQL查询语句
示例3:
???@Test ???//持久化状态对象其实就是放入session缓存中的对象 ???public void fun3(){ ???????//1 获得session ???????Session session = HibernateUtils.openSession(); ???????//2 控制事务 ???????Transaction tx = session.beginTransaction(); ???????//3执行操作 ???????????????Customer c1 = new Customer(); ???????c1.setCust_id(1l);//托管|游离 ???????????????session.update(c1);//c1被放入session缓存了 ???????????????????????Customer c2 = session.get(Customer.class, 1l); ???????????????//4提交事务.关闭资源 ???????tx.commit(); ???????session.close();// 游离|托管 状态, 有id , 没有关联 ???????????????????}
这段代码运行中,打印SQL的UPDATE语句
原因:缓存中不存在快照,c1放入session缓存中对比快照时候必然不一致,而c2这一句调用get方法后,依照上边的原理,才会运行SQL的UPDATE语句
所以,这段代码中真正使hibernate发送SQL语句的是c2这一行
hibernate框架学习笔记5:缓存
原文地址:https://www.cnblogs.com/xuyiqing/p/8449143.html