hibernate12--缓存
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.url"> jdbc:oracle:thin:@localhost:1521:orcl </property> <property name="connection.username">t10</property> <property name="connection.password">t10</property> <property name="connection.driver_class"> oracle.jdbc.OracleDriver </property> <!--方言 --> <property name="dialect"> org.hibernate.dialect.Oracle9Dialect </property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">update</property> <!-- 在我们的项目中使用currentSession--> <property name="current_session_context_class">thread</property> <!-- 开启配置2级缓存 --> <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> <!--加载我们配置的映射文件 全路径 --> <mapping resource="cn/bdqn/bean/Dept.hbm.xml" /> <mapping resource="cn/bdqn/bean/Emp.hbm.xml" /> </session-factory> </hibernate-configuration>
<?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.bdqn.bean"> <class name="Emp"> <!-- 配置2级缓存策略 --> <cache usage="read-only"/> <id name="empNo"> <generator class="assigned"/><!-- 手动给主键赋值 --> </id> <property name="empName"/> <property name="job"/> <property name="sal" column="salary"/> <property name="hireDate"/> <!-- 配置多对一关联 name:对应的是 本类中 关联关系的属性名 column:对应数据库中 两个表的 外键! class:关联的实体类 --> <many-to-one name="dept" column="DEPTNO" class="Dept"/> </class> </hibernate-mapping>
<ehcache> <!-- java.io.tmpdir:临时系统文件! 可以换成自己创建的目录下 --> <diskStore path="java.io.tmpdir"/> <!-- maxElementsInMemory:在内存中 最大的存储量 10000对象 eternal:是否永远不销毁 timeToIdleSeconds:当前缓存的数据闲置多少时间被销毁 以秒为单位 timeToLiveSeconds:当前缓存的数据超过多少时间被销毁 以秒为单位 overflowToDisk: 是否写入磁盘 diskPersistent:硬盘文件是否永久保存 memoryStoreEvictionPolicy: 缓存清理策略: FIFO ,first in first out (先进先出). LFU , Less Frequently Used (最少使用). 意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存。 LRU ,Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了, 而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" memoryStoreEvictionPolicy="LRU" /> </ehcache>
package cn.bdqn.test; import java.util.ArrayList; import java.util.List; import oracle.net.aso.s; import org.hibernate.CacheMode; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Property; import org.hibernate.criterion.Restrictions; import org.hibernate.transform.Transformers; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.sun.org.apache.xml.internal.security.encryption.Transforms; import cn.bdqn.bean.Dept; import cn.bdqn.bean.Emp; import cn.bdqn.util.HibernateUtil; public class EmpTest { /** * 1级缓存: session中的缓存 * clear():清空session中所有的缓存对象 * evict():清除session中指定的对象 */ @Test public void test01(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp = (Emp) session.get(Emp.class, 1); // 产生1条sql session.clear(); //清空缓存 emp = (Emp) session.get(Emp.class, 1); //产生1条sql } @Test public void test02(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp = (Emp) session.load(Emp.class, 1); session.clear(); //清空缓存 emp = (Emp) session.load(Emp.class, 1); } @Test public void test03(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp1 = (Emp) session.get(Emp.class, 1); //产生1条sql Emp emp2 = (Emp) session.get(Emp.class, 2); //产生1条sql session.evict(emp1); //清除指定的 } @Test public void test04(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp=new Emp(); emp.setEmpNo(51); emp.setEmpName("haha"); session.save(emp); session.evict(emp); //清除指定的 transaction.commit(); // 能保存到数据库中吗? 肯定不能保存 除非把 session.evict(emp); 去掉 } @Test public void test05(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp=new Emp(); emp.setEmpNo(52); emp.setEmpName("haha"); session.save(emp); //持久态 System.out.println("********"); session.flush(); //产生sql语句 把 emp对象 同步到 数据库 System.out.println("********"); session.evict(emp); //清除指定的 但是 已经 清理了 缓存 transaction.commit(); // 能保存到数据库中,因为已经flush } @Test public void test06(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp=(Emp) session.get(Emp.class, 1); //持久化 emp.setEmpName("haha"); //emp 脏对象 System.out.println("flush前******************"); session.flush(); //同步数据库 System.out.println("flush后******************"); emp=(Emp) session.get(Emp.class, 1); //持久化 System.out.println(emp.getEmpName()); //输出 haha 证明同步到数据库中了 emp.setEmpName("heihei"); //emp 脏对象 transaction.commit(); } /** * 2级缓存: 进程或者是集群范围内的缓存!是sessionFactory的缓存! * 一个sessionFactory可以创建N个session! * 也就是说 在2级缓存中的数据,N个session共享! * * * 2级缓存适合存放的数据: * 01.不经常被修改的数据 * 02.不敏感的数据 (财务数据不能放入) * 03.共享的数据 * * * 配置ehCache缓存 * 01.引入jar * 02.找到对应xml文件 * 03.在hibernate.cfg.xml文件中 开启和配置缓存 * 04.在对应的映射文件中 配置 缓存的策略 */ @Test public void test07(){ //之前是 两条sql语句 Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp = (Emp) session.get(Emp.class, 1); // 产生1条sql session.clear(); //清空缓存 emp = (Emp) session.get(Emp.class, 1); } /** * 验证我们 映射文件中的 <cache usage="read-only"/> */ @Test public void test08(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp = (Emp) session.get(Emp.class, 1); // 产生1条sql emp.setEmpName("hahaahaha"); session.update(emp); transaction.commit(); //报错 can't writer to readonly object!! } //java.io.tmpdir:临时系统文件! 可以换成自己创建的目录下 @Test public void test09(){ System.out.println(System.getProperty("java.io.tmpdir")); } /** * 设置2级缓存 模式 * CacheMode.IGNORE: 不与2级缓存关联 产生2条sql * CacheMode.NORMAL:与2级缓存关联,可读可写 产生1条sql * CacheMode.GET:与2级缓存关联,只读 产生1条sql * CacheMode.PUT:与2级缓存关联,只写 产生2条sql * CacheMode.REFRESH:与2级缓存关联,只写 * 通过 hibernate.cache.use_minimal_puts 的设置,强制二级缓存从数据库中读取数据,刷新缓存内容。 * 产生2条sql */ @Test public void test10(){ Session session = HibernateUtil.getCurrentSession(); Transaction transaction = session.beginTransaction(); Emp emp = (Emp) session.get(Emp.class, 1); // 产生1条sql session.clear(); //设置缓存模式 session.setCacheMode(CacheMode.REFRESH); emp = (Emp) session.get(Emp.class, 1); } /* * 查询缓存 * 基于2级缓存! * 第一次在网页中查询一个关键字 为 java的所有 页面 可能需要等待 2S * 第2次在网页中查询一个关键字 为 java的所有 页面 必须 小于2S * * 01.去核心配置文件中配置 * <property name="cache.use_query_cache">true</property> * 02.手动开启查询缓存 * query.setCacheable(true); */ @Test public void test11(){ Session session = HibernateUtil.getCurrentSession(); Query query = session.createQuery("from Dept"); query.setCacheable(true); //首次开启 ! 之后如果还是这个query语句,那么就会启动查询缓存 List list = query.list(); for (Object object : list) { System.out.println(object); } System.out.println("****************************"); Query query2 = session.createQuery("from Dept"); query2.setCacheable(true); //先去 查询缓存中查找 List list2 = query2.list(); for (Object object : list2) { System.out.println(object); } System.out.println("****************************"); Query query3 = session.createQuery("from Dept"); //query3.setCacheable(true); List list3 = query3.list(); for (Object object : list3) { System.out.println(object); } session.close(); } }