Hibernate笔记④--一级二级缓存、N+1问题、saveorupdate、实例代码
一级缓存及二级缓存
一级缓存也是Session 缓存
一个链接用户的多次查询使用缓存
跨用户 则无缓存
hibernate自带的
get和load都会填充并利用一级缓存
二级缓存(需要我们自己配置)
SessionFactory 缓存
可以跨用户的
list 方法会使用一级缓存 ,但是不会填充一级缓存
iterator会填充过一级缓存 耗时的
N+1问题
当我们使用iterate 进行迭代 又要使用内部的数据,则会发送1+n条sql
第一条先load 拿到id 对象改变对象则会改变
再取get每一个的id
Saveor update
/* * 如果一个对先查找出来的,则会调用update语句 * 如果没有查 则调用insert语句 */ public static void testSaveorUpdate(Emp e){ Session session=HibernateSessionFactory.getSession(); Transaction tx=session.beginTransaction(); session.saveOrUpdate(e); tx.commit(); HibernateSessionFactory.closeSession(); } |
例子代码
package com.pcx.dao;
import java.util.Iterator; import java.util.List;
import org.hibernate.Session;
import com.pcx.model1.Dept; import com.pcx.model1.Emp; import com.pcx.util.HibernateSessionFactory;
public class CacheTest { public static void main(String[] args) { Emp e=fetchTest2(); System.out.println(e.getDept()); } // public static void cacheTest(){ Session session=HibernateSessionFactory.getSession(); Emp emp=(Emp) session.get(Emp.class, 1);
System.out.println(emp.getName());
Emp emp1=(Emp) session.get(Emp.class, 1);
System.out.println(emp1.getName()); HibernateSessionFactory.closeSession();
} //get和load都是會填充一级缓存的 public static void cacheTest2(){ Session session=HibernateSessionFactory.getSession(); Emp emp=(Emp) session.load(Emp.class, 1);
System.out.println(emp.getName());
Emp emp1=(Emp) session.get(Emp.class, 1);
System.out.println(emp1.getName()); HibernateSessionFactory.closeSession();
}
public static void cacheTest3(){ Session session=HibernateSessionFactory.getSession(); String hql="from Emp e where e.id=1";
List<Emp> emps=session.createQuery(hql).list(); for (Emp emp : emps) { System.out.println(emp.getName()); }
//这儿没有用上一级缓存 List<Emp> emps2=session.createQuery(hql).list(); for (Emp emp : emps2) { System.out.println(emp.getName()); } HibernateSessionFactory.closeSession();
} public static void testload(){ Session session=HibernateSessionFactory.getSession(); Emp e=(Emp) session.load(Emp.class, 2);
System.out.println(e.getId()); System.out.println(e.getName()); e.setName("lllll"); HibernateSessionFactory.closeSession(); } //n+1问题 //当我们使用iterate 进行迭代 又要使用内部的数据,则会发送1+n条sql //第一条先load拿到id 对象改变9对象则会改变
// 再取get每一个的id /** * */ public static void cacheTest4(){ Session session=HibernateSessionFactory.getSession(); String hql="from Emp";
Iterator<Emp> iter=session.createQuery(hql).iterate(); while (iter.hasNext()) { Emp e=iter.next(); System.out.println(e.getName());
} HibernateSessionFactory.closeSession();
} /** * 配置二级缓存最好的方式是在每个类的配置 添加 <cache usage="read-only"/>标记 */ public static void cacheTest5(){ Session session=HibernateSessionFactory.getSession(); Emp emp=(Emp) session.get(Emp.class, 1);
System.out.println(emp.getName()); session.evict(emp);//清理一级缓存 //如果二级缓存关闭的话会查询两次 Emp emp1=(Emp) session.get(Emp.class, 1);
System.out.println(emp1.getName()); HibernateSessionFactory.closeSession(); } public static void cacheTest6(){ Session session=HibernateSessionFactory.getSession(); Emp emp=(Emp) session.get(Emp.class, 1);
System.out.println(emp.getName()); session.evict(emp);//清理一级缓存 //如果二级缓存关闭的话会查询两次 Session session2=HibernateSessionFactory.getSession(); Emp emp1=(Emp) session2.get(Emp.class, 1);
System.out.println(emp1.getName()); HibernateSessionFactory.closeSession(); } /* * 抓取策略 * Fetch 为join的话 就没有lazy了 就直接把dept对象都加载了 */ public static Emp fetchTest2(){ Session session=HibernateSessionFactory.getSession(); Emp emp=(Emp) session.load(Emp.class, 1); Dept d=emp.getDept();
// System.out.println(emp.getName()); // System.out.println(d.getName()); HibernateSessionFactory.closeSession(); return emp; } } |
Fecat="join"
fatch 默认只就是select
join 也将关联的对象一并加载进
来了,并不管是否懒加载
错误:No row with the given identifier exists: [com.pcx.model1.Emp#1000]
at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:386)
说明表中没有本条数据