1.一級(jí)緩存的作用域是一個(gè)session的范圍
2.使用二級(jí)緩存的步驟
··hibernate并沒(méi)有提供相應(yīng)的二級(jí)緩存的組件,所以需要加入額外的二級(jí)緩存包,常用的二級(jí)緩存包是ECHcache
在hibernate.cfg.xml中配置開(kāi)啟二級(jí)緩存
<propertyname="hibernate.cache.use_second_level_cache">true</property>
設(shè)置二級(jí)緩存所提供的類(lèi)
<propertyname="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.EhCacheProvider</property>
在hibernate4.0之后需要設(shè)置facotory_class
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
說(shuō)明ehcache的配置文件路徑
<property name="hibernate.cache.provider_configuration_file_resource_path">
ehcache.xml</property>
應(yīng)用二級(jí)緩存:
在xml的配置文件中設(shè)置二級(jí)緩存
try {
//此時(shí)會(huì)發(fā)出一條sql取出所有的學(xué)生信息
session = HibernateUtil.openSession();
Student stu = (Student)session.load(Student.class, 1);
System.out.println(stu.getName()+",---");
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtil.close(session);}
try {
session = HibernateUtil.openSession();
session.beginTransaction();
//此時(shí)session已經(jīng)關(guān)閉了,但是Student在二級(jí)緩存中,所以也不會(huì)發(fā)出SQL語(yǔ)句
Student stu = (Student)session.load(Student.class, 1);
//會(huì)報(bào)錯(cuò),因?yàn)槎?jí)緩存設(shè)置為read-only
// stu.setName("abc");
System.out.println(stu.getName()+",---");
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtil.close(session);}
二級(jí)緩存緩存的是對(duì)象,它是把所有的對(duì)象緩存到內(nèi)存中,一定注意是基于對(duì)象的緩存
try {/** * 此時(shí)會(huì)發(fā)出一條sql取出所有的學(xué)生信息 */
session = HibernateUtil.openSession();
List<Object[]>ls = session.createQuery("select stu.id,stu.name from Student stu")
.setFirstResult(0).setMaxResults(50).list();
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtil.close(session);}
try {
session = HibernateUtil.openSession();
session.beginTransaction();
//以上代碼僅僅取了id和name,而二級(jí)緩存是緩存對(duì)象的,所以上一段代碼不會(huì)將對(duì)象加入二級(jí)緩存
*此時(shí)就是發(fā)出相應(yīng)的sql
Student stu = (Student)session.load(Student.class, 1);
//會(huì)報(bào)錯(cuò),因?yàn)槎?jí)緩存設(shè)置為read-only
// stu.setName("abc");
System.out.println(stu.getName()+",---");
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtil.close(session);}
try {
/** * 此時(shí)會(huì)發(fā)出一條sql取出所有的學(xué)生信息 */
session = HibernateUtil.openSession();
List<Student>ls = session.createQuery("select stu from Studentstu").setFirstResult(0).setMaxResults(50).list();}
catch (Exception e) {
e.printStackTrace();}
finally {HibernateUtil.close(session);}
try {
session = HibernateUtil.openSession();
/** * 由于學(xué)生的對(duì)象已經(jīng)緩存在二級(jí)緩存中了,此時(shí)再使用iterate來(lái)獲取對(duì)象的時(shí)候,首先會(huì)通過(guò)一條 取id的語(yǔ)句,然后在獲取對(duì)象時(shí)去二級(jí)緩存中,如果發(fā)現(xiàn)就不會(huì)再發(fā)SQL,這樣也就解決了N+1問(wèn)題? 而且內(nèi)存占用也不多 */
Iteratorstus = session.createQuery("from Student")
.setFirstResult(0).setMaxResults(50).iterate();
for(;stus.hasNext();) {
Student stu = stus.next();
System.out.println(stu.getName());}
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtil.close(session);}
try {
/** * 此時(shí)會(huì)發(fā)出一條sql取出所有的學(xué)生信息 */
session = HibernateUtil.openSession();
List<Student>ls = session.createQuery("select stu from Student stu").setFirstResult(0).setMaxResults(50).list();}
catch (Exception e) {e.printStackTrace();}
finally {HibernateUtil.close(session);}
try {session = HibernateUtil.openSession();
/** * 使用List會(huì)發(fā)出兩條一模一樣的sql,此時(shí)如果希望不發(fā)sql就需要使用
查詢(xún)緩存 */
List<Student>ls = session.createQuery("select stu from Studentstu").setFirstResult(0).setMaxResults(50).list();
Iterator<Student>stus = ls.iterator();
for(;stus.hasNext();) {
Student stu = stus.next();
System.out.println(stu.getName());}
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateUtil.close(session);}
查詢(xún)緩存是針對(duì)HQL語(yǔ)句的緩存,查詢(xún)緩存僅僅只會(huì)緩存id而不會(huì)緩存對(duì)象,
查詢(xún)緩存未完待續(xù)....