缓存不止存在与程序中,电脑硬件乃至于生活中都存在缓存
目的:提高效率
比如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这一行