Hibernate---缓存
1、为什么要用Hibernate缓存?
Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
2、Hibernate缓存分为几种?
(1)一级缓存:也叫作Session缓存,在同一个session调用get()或者load()方法的时候使用
(2)二级缓存:也叫作SessionFactory缓存,在同一个SesssionFactory中,不同Session调用get()或者load()方法的时候调用。二级缓存默认不打开。
(3)查询缓存:在使用hql查询的时候使用。查询缓存默认不打开。
3、使用缓存的步骤是什么?
(1)使用一级缓存,不需要格外的操作。在同一个session中查询用一条数据,便可知道它的存在。
(2)使用二级缓存需要进行的操作如下:
(a)在hibernate.cfg.xml中配置如下信息,来开启二级缓存:
<!-- 开启二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- /开启二级缓存 -->
(b)在需要缓存的类的映射文件(此处是User.hbm.xml)中配置如下信息:
<cache usage="read-only"/>
(c)添加commons-logging-1.1.jar包
(3)使用查询缓存需要在hibernate.cfg.xml中配置如下信息,来开启查询缓存:
<!-- 开启三级缓存 -->
<property name="cache.use_query_cache">true</property>
<!-- /开启三级缓存 -->
4、具体的实例如下:
package com.etc.dao;
import java.util.List;
import javax.security.auth.login.CredentialException;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
public class UserDAOTest {
/**
* Description:一级缓存:session缓存,在session的开始和结束之间,查询同一条数据,只发起一次sql请求,第二次直接从缓存中取
* 一级缓存:是同一个session调用get()或者load()方法使用的
* 控制台打印的信息如下:
* Hibernate:
* select
* user0_.user_id as user1_0_0_,
* user0_.user_name as user2_0_0_
* from
* test.t_user user0_
* where
* user0_.user_id=?
* User [id=1, username=zoey1]
* User [id=1, username=zoey1]
* true
* ===============session关闭之后新建一个session====================
*Hibernate:
* select
* user0_.user_id as user1_0_0_,
* user0_.user_name as user2_0_0_
* from
* test.t_user user0_
* where
* user0_.user_id=?
* User [id=1, username=zoey1]
* @author zoey
* @date 2017年7月28日
*/
@Test
public void testSession(){
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
/**
* 第一次执行查询时,发起一次sql,从数据库查询中返回数据,
* 同时将这条数据放入session缓存中,也就是放在内存中作为副本
*/
User user1 = (User)session.get(User.class,1);
System.out.println(user1);
User user2 = (User)session.get(User.class,1);//第二次查询时,直接从缓存中查询,返回内存的副本
System.out.println(user2);
System.out.println(user1 == user2);//true,两者是同一个对象,地址都一样
session.getTransaction().commit();
System.out.println("===============session关闭之后新建一个session====================");
Session session2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
User user3 = (User)session2.get(User.class,1);//关闭session之后,查询同一条数据,仍旧会从数据库中查询,而不是直接从缓存中读取
//不同session用的是不同的缓存
System.out.println(user3);
session2.getTransaction().commit();
}
/**
* Description:二级缓存:SessionFactory缓存,默认不开启,想要开启时需要在hibernate.cfg.xml中配置相应的参数
* <property name="cache.use_second_level_cache">true</property>
* <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
* 还需要在要缓存的类的映射文件中配置cache属性
* <cache usage="read-only"/>
* 还需要加入commons-logging-1.1.jar包
* 二级缓存:是不同的session调用get()或者load()方法使用的
* 控制台打印的信息如下:
* Hibernate:
* select
* user0_.user_id as user1_0_0_,
* user0_.user_name as user2_0_0_
* from
* test.t_user user0_
* where
* user0_.user_id=?
* User [id=1, username=zoey1]
* ===============session关闭之后新建一个session====================
* User [id=1, username=zoey1]
* @author zoey
* @date 2017年7月28日
*/
@Test
public void testSessionFactory(){
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
User user1 = (User)session.get(User.class,1);//首先会用一级缓存
System.out.println(user1);
session.getTransaction().commit();//session关闭之后,一级缓存失效,二级缓存开启,开始生效
System.out.println("===============session关闭之后新建一个session====================");
Session session2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
User user2 = (User)session2.get(User.class,1);//先使用一级缓存查找,没有数据,再从二级缓存中查找,可以查找到数据
System.out.println(user2);
session2.getTransaction().commit();
}
/**
* Description:三级缓存:查询缓存:默认不开启,需要在hibernate.cfg.xml中配置相应的属性才开启
* <property name="cache.use_query_cache">true</property>
* 三级缓存:在hql调用的时候使用的
* 控制台打印的信息如下:
* Hibernate:
* select
* user0_.user_id as user1_0_,
* user0_.user_name as user2_0_
* from
* test.t_user user0_
* 10
* 10
* @author zoey
* @date 2017年7月28日
*/
@Test
public void testQuery(){
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
String hql = "from User";//只有hibernate查询语句才能用三级缓存
List<User> userlist1 = session.createQuery(hql).setCacheable(true).list();//第一次查询时,从数据库中查询数据
System.out.println(userlist1.size());
//hql语句会进行字符串比较,如果hql查询语句相同,则不再从数据库中查询,而是从三级缓存中读取
List<User> userlist2 = session.createQuery(hql).setCacheable(true).list();//第二次查询时,直接从三级缓存中读取
System.out.println(userlist1.size());
session.getTransaction().commit();
}
}
User.java类如下:
package com.etc.dao;
public class User {
private int id;
private String username;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + "]";
}
}
User.hbm.xml映射文件如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.etc.dao.User" table="t_user" catalog="test">
<!-- 在具体需要缓存的类中配置 cache -->
<cache usage="read-only" />
<id name="id" type="java.lang.Integer">
<column name="user_id" />
<generator class="native" />
</id>
<property name="username" type="java.lang.String">
<column name="user_name" />
</property>
</class>
</hibernate-mapping>
hibernate.cfg.xml配置文件如下:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<!-- 开启二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- /开启二级缓存 -->
<!-- 开启三级缓存 -->
<property name="cache.use_query_cache">true</property>
<!-- /开启三级缓存 -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- <property name="hbm2ddl.auto">create</property> -->
<property name="current_session_context_class">thread</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="myeclipse.connection.profile">com.mysql.jdbc.Driver</property>
<mapping resource="com/etc/dao/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>