概述:
Hibernate是一个持久层框架,经常访问物理数据库。为了降低应用程序对物理数据源访问的频次,从
而提高应用程序的运行性能,缓存的合理使用就尤为重要。缓存内的数据是对物理数据源中的数据的复制,
应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
一级和二级缓存:
应用原理:
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓
存,那么从二级缓存中查;如果都查不到,再查询数据库,把结果按照ID放入到缓存删除、更新、增加数据
的时候,同时更新缓存。
一级缓存的应用:
当session对象调用save()方法保存一个对象后,该对象会被放入到session的缓存中。get()和
load()。当session对象调用get()或load()方法从数据库取出一个对象后,该对象也会被放入到session的缓
存中。使用HQL和QBC等从数据库中查询数据。
<span style="font-size:18px;">public class Client
{
public static void main(String[] args)
{
Session session =HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try
{
/*开启一个事务*/
tx =session.beginTransaction();
/*从数据库中获取id="001"的Person对象*/
Person person= (Person )session.get(Person .class,"001");
System.out.println("person.getUsername is"+person.getUsername());
/*事务提交*/
tx.commit();
System.out.println("-------------------------------------");
/*开启一个新事务*/
tx =session.beginTransaction();
/*从数据库中获取id="402881e534fa5a440134fa5a45340002"的Customer对象*/
Person person1= (Person )session.get(Person .class,"001");
System.out.println("person1.getUsername is"+person1.getUsername());
/*事务提交*/
tx.commit();
System.out.println("-------------------------------------");
/*比较两个get()方法获取的对象是否是同一个对象*/
System.out.println("person== person1result is "+(person==person1));
}
catch (Exceptione)
{
if(tx!=null)
{
tx.rollback();
}
}
finally
{
session.close();
}
}
}</span>
结果:
Hibernate:
select
person0_.id asid0_0_,
person0_.username asusername0_0_,
person0_.balance asbalance0_0_
from
person person0_
where
person0_.id=?
person.getUsernameislisi
-------------------------------------
person.getUsernameislisi
-------------------------------------
person== person1result is true
结果中只包含了一条SELECTSQL语句,而且person==person1 result istrue说明两个取出来的对象是
同一个对象。其原理是:第一次调用get()方法,Hibernate先检索缓存中是否有该查找对象,发现没有,
Hibernate发送SELECT语句到数据库中取出相应的对象,然后将该对象放入缓存中,以便下次使用,第二次调
用get()方法,Hibernate先检索缓存中是否有该查找对象,发现正好有该查找对象,就从缓存中取出来,不
再去数据库中检索。
总结:
Hibernate 的缓存只从下面两个方面发生作用 :1.通过主键值加载对象 2.延迟加载 。通过主键值
加载就会存在N+1问题,我们将在下篇文章介绍通过二级缓存解决N+1问题。而延迟加载实现要解决两个问
题:
1.正常关闭连接和确保请求中访问的是同一个session。
2.http请求结束后正确的关闭session(过滤器实现了session的正常关闭),延迟加载必须保证是同一个
session(session绑定在ThreadLocal)。