hibernate 一級(jí)緩存:(緩存的是實(shí)體對(duì)象)
一級(jí)緩存很短和session的生命周期一致,一級(jí)緩存也叫session級(jí)的緩存或事務(wù)緩存
哪些方法支持一級(jí)緩存:
*get()
*load()
*iterate() (查詢(xún)實(shí)體對(duì)象)
如何管理一級(jí)緩存:
* session.clear() session.evict()
如何避免一次性大量的實(shí)體數(shù)據(jù)入庫(kù)導(dǎo)致內(nèi)存溢出
*先f(wàn)lush,再clear
如果數(shù)據(jù)量特別大,考慮采用jdbc實(shí)現(xiàn),如果jdbc也不能滿(mǎn)足要求,可以考慮采用數(shù)據(jù)庫(kù)本身的特定導(dǎo)入工具
一.Load測(cè)試: 在同一個(gè)session中發(fā)出兩次load查詢(xún)
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
在同一個(gè)session中發(fā)出兩次load查詢(xún),第一次load的時(shí)候不會(huì)去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗荓AZY的,當(dāng)使用的時(shí)候才去查詢(xún)數(shù)據(jù)庫(kù), 第二次load的時(shí)候也不會(huì),當(dāng)使用的時(shí)候也不會(huì)查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗诰彺胬镎业剑粫?huì)發(fā)出sql
Load測(cè)試: 開(kāi)啟兩個(gè)session中發(fā)出兩次load查詢(xún)
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
sessioin.close();
………..
sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
開(kāi)啟兩個(gè)session中發(fā)出兩次load查詢(xún),第一次load的時(shí)候不會(huì)去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗荓AZY的,當(dāng)使用的時(shí)候才去查詢(xún)數(shù)據(jù)庫(kù), 第二次load的時(shí)候也不會(huì),當(dāng)使用的時(shí)候查詢(xún)數(shù)據(jù)庫(kù),因?yàn)閟ession間不能共享一級(jí)緩存的數(shù)據(jù),因?yàn)樗麜?huì)隨session的生命周期存在和消亡
二.Get測(cè)試: 在同一個(gè)session中發(fā)出兩次get查詢(xún)
Student sutdent = (Student)session.get(Student.class,1);
System.out.println(student.getName());
sutdent = (Student)session.get(Student.class,1);
System.out.println(student.getName());
在同一個(gè)session中發(fā)出兩次get查詢(xún), 第一次get的時(shí)候去查詢(xún)數(shù)據(jù)庫(kù),第二次get的時(shí)候不會(huì)查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗诰彺胬镎业剑粫?huì)發(fā)出sql
三.iterate測(cè)試: 在同一個(gè)session中發(fā)出兩次iterator查詢(xún)
Student student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next();
System.out.println(student.getName());
student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next();
System.out.println(student.getName());
在同一個(gè)session中發(fā)出兩次iterator查詢(xún),第一次iterate().next()的時(shí)候會(huì)發(fā)出查詢(xún)id的sql,使用的時(shí)候會(huì)發(fā)出相應(yīng)的查詢(xún)實(shí)體對(duì)象,第二次iterate().next()的時(shí)候會(huì)發(fā)出查詢(xún)id的sql,不會(huì)發(fā)出查詢(xún)實(shí)體對(duì)象的sql,因?yàn)閕terate使用緩存,不會(huì)發(fā)出sql
四.Iterate查詢(xún)屬性測(cè)試: 同一個(gè)session中發(fā)出兩次查詢(xún)屬性
String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next();
System.out.println(name);
String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next();
System.out.println(name);
在同一個(gè)session中發(fā)出兩次查詢(xún)屬性, 第一次iterate().next()的時(shí)候會(huì)發(fā)出查詢(xún)屬性的sql,第二次iterate().next()的時(shí)候會(huì)發(fā)出查詢(xún)屬性的sql,iterate查詢(xún)普通屬性,一級(jí)緩存不會(huì)緩存,所以會(huì)發(fā)出sql
五.同一個(gè)session中先save,再發(fā)出load查詢(xún)save過(guò)的數(shù)據(jù)
Student stu = new Student();
stu.setName(“王五”);
Serializable id = session.save(stu);
Student sutdent = (Student)session.load(Student.class,id);
System.out.println(student.getName());
save的時(shí)候,他會(huì)在緩存里放一份,不會(huì)發(fā)出sql,因?yàn)閟ave是使用緩存的
六.同一個(gè)session中先調(diào)用load查詢(xún),然后執(zhí)行sessio.clear()或session.evict(),再調(diào)用load查詢(xún)
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
session.clear();
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
sessio.clear()或session.evict()可以管理一級(jí)緩存,一級(jí)緩存無(wú)法取消,但可以管理.
上面的語(yǔ)句都會(huì)發(fā)出sql 因?yàn)橐患?jí)緩存中的實(shí)體被清除了
七.向數(shù)據(jù)庫(kù)中批量加入1000條數(shù)據(jù)
for(int i=0;i<1000;i++){
Student student = new Student();
student.setName(“s” + i);
session.save(student);
//每20條數(shù)據(jù)就強(qiáng)制session將數(shù)據(jù)持久化,同時(shí)清除緩存,避免大量數(shù)據(jù)造成內(nèi)存溢出
if( i %20 == 0 ){
session.flush();
session.clear();
}
}
=========================================================================================
hibernate 二級(jí)緩存:(緩存的是實(shí)體對(duì)象,二級(jí)緩存是放變化不是很大的數(shù)據(jù))


二級(jí)緩存也稱(chēng)進(jìn)程級(jí)的緩存或SessionFactory級(jí)的緩存,而二級(jí)緩存可以被所有的session(hibernate中的)共享二級(jí)緩存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二級(jí)緩存
二級(jí)緩存的配置和使用:
1.將echcache.xml文件拷貝到src下, 二級(jí)緩存hibernate默認(rèn)是開(kāi)啟的,手動(dòng)開(kāi)啟
2.開(kāi)啟二級(jí)緩存,修改hibernate.cfg.xml文件,
<property name=”hibernate.cache.user_second_level_cache”>true</property>
3.指定緩存產(chǎn)品提供商
<property name=”hibernate.cache.provider_calss”>org.hibernate.cache.EhCacheProvider</property>
4.指定那些實(shí)體類(lèi)使用二級(jí)緩存(兩種方法,推薦使用第二種)
第一種:在*.hbm.xml中,在<id>之前加入
<cache usage=”read-only” />, 使用二級(jí)緩存
第二種:在hibernate.cfg.xml配置文件中,在<mapping resource=”com/Studnet.hbm.xml” />后面加上:
<class-cache class=” com.Studnet” usage=”read-only” />
二級(jí)緩存是緩存實(shí)體對(duì)象的
了解一級(jí)緩存和二級(jí)緩存的交互
測(cè)試二級(jí)緩存:
一.開(kāi)啟兩個(gè)session中發(fā)出兩次load查詢(xún)(get與load一樣,同樣不會(huì)查詢(xún)數(shù)據(jù)庫(kù)),
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
sessioin.close();
………..
sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
開(kāi)啟兩個(gè)session中發(fā)出兩次load查詢(xún),第一次load的時(shí)候不會(huì)去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗荓AZY的,當(dāng)使用的時(shí)候才去查詢(xún)數(shù)據(jù)庫(kù), 第二次load的時(shí)候也不會(huì),當(dāng)使用的時(shí)候查詢(xún)數(shù)據(jù)庫(kù),開(kāi)啟了二級(jí)緩存,也不會(huì)查詢(xún)數(shù)據(jù)庫(kù)。
二.開(kāi)啟兩個(gè)session,分別調(diào)用load,再使用sessionFactory清楚二級(jí)緩存
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
sessioin.close();
………..
SessionFactory factory = HibernateUtil.getSessionFactory();
//factory.evict(Student.class); //清除所有Student對(duì)象
Factory.evict(Student.class,1); //清除指定id=1 的對(duì)象
sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
開(kāi)啟兩個(gè)session中發(fā)出兩次load查詢(xún),第一次load的時(shí)候不會(huì)去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗荓AZY的,當(dāng)使用的時(shí)候才去查詢(xún)數(shù)據(jù)庫(kù), 第二次load的時(shí)候也不會(huì),當(dāng)使用的時(shí)候查詢(xún)數(shù)據(jù)庫(kù),它要查詢(xún)數(shù)據(jù)庫(kù),因?yàn)槎?jí)緩存中被清除了
三.一級(jí)緩存和二級(jí)緩存的交互
session.setCacheMode(CacheMode.GET); //設(shè)置成 只是從二級(jí)緩存里讀,不向二級(jí)緩存里寫(xiě)數(shù)據(jù)
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
sessioin.close();
………..
SessionFactory factory = HibernateUtil.getSessionFactory();
//factory.evict(Student.class); //清除所有Student對(duì)象
Factory.evict(Student.class,1); //清除指定id=1 的對(duì)象
sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
開(kāi)啟兩個(gè)session中發(fā)出兩次load查詢(xún),第一次load的時(shí)候不會(huì)去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗荓AZY的,當(dāng)使用的時(shí)候才去查詢(xún)數(shù)據(jù)庫(kù), 第二次load的時(shí)候也不會(huì),當(dāng)使用的時(shí)候查詢(xún)數(shù)據(jù)庫(kù),它要查詢(xún)數(shù)據(jù)庫(kù),因?yàn)?設(shè)置了CacheMode為GET,(load設(shè)置成不能往二級(jí)緩沖中寫(xiě)數(shù)據(jù)), 所以二級(jí)緩沖中沒(méi)有數(shù)據(jù)
session.setCacheMode(CacheMode.PUT); //設(shè)置成只是向二級(jí)緩存里寫(xiě)數(shù)據(jù),不讀數(shù)據(jù)
Student sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
sessioin.close();
………..
SessionFactory factory = HibernateUtil.getSessionFactory();
//factory.evict(Student.class); //清除所有Student對(duì)象
Factory.evict(Student.class,1); //清除指定id=1 的對(duì)象
sutdent = (Student)session.load(Student.class,1);
System.out.println(student.getName());
開(kāi)啟兩個(gè)session中發(fā)出兩次load查詢(xún),第一次load的時(shí)候不會(huì)去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樗荓AZY的,當(dāng)使用的時(shí)候才去查詢(xún)數(shù)據(jù)庫(kù), 第二次load的時(shí)候也不會(huì),當(dāng)使用的時(shí)候查詢(xún)數(shù)據(jù)庫(kù),它要查詢(xún)數(shù)據(jù)庫(kù),因?yàn)樵O(shè)置了CacheMode為POST,(load設(shè)置成只是向二級(jí)緩存里寫(xiě)數(shù)據(jù),不讀數(shù)據(jù))
====================================================================================
hibernate查詢(xún)緩存(hibernate默認(rèn)是關(guān)閉的)
查詢(xún)緩存是針對(duì)普通屬性結(jié)果集的緩存
對(duì)實(shí)體對(duì)象的結(jié)果集只緩存id
查詢(xún)緩存的生命周期,當(dāng)前關(guān)聯(lián)的表發(fā)生修改,那么查詢(xún)緩存生命周期結(jié)束
查詢(xún)緩存的配置和使用:
1. 啟用查詢(xún)緩存:在hibernate.cfg.xml中加入:
<property name=”hibernate.cache.use_query_cache”>true</property>
2. 在程序中必須手動(dòng)啟用查詢(xún)緩存,如:query.setCacheable(true);
測(cè)試查詢(xún)緩存:
一. 開(kāi)啟查詢(xún)緩存,關(guān)閉二級(jí)緩存,開(kāi)啟一個(gè)session,分別調(diào)用query.list (查詢(xún)屬性)
Query query = session.createQuery(“select s.name from Student s”);
//啟用查詢(xún)緩存
query.setCacheable(true);
List names = query.list();
for(Iterator iter = names.terator();iter.hasNext();){
String name = (String)iter.next();
System.out.println(name);
}
System.out.println(“------------------------------------------”);
query = session.createQuery(“select s.name from Student s”);
//啟用查詢(xún)緩存
query.setCacheable(true);
names = query.list();
for(Iterator iter = names.terator();iter.hasNext();){
String name = (String)iter.next();
System.out.println(name);
}
第二次沒(méi)有去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)閱⒂昧瞬樵?xún)緩存
二. 開(kāi)啟查詢(xún)緩存,關(guān)閉二級(jí)緩存,開(kāi)啟兩個(gè)session,分別調(diào)用query.list (查詢(xún)屬性)
Query query = session.createQuery(“select s.name from Student s”);
//啟用查詢(xún)緩存
query.setCacheable(true);
List names = query.list();
for(Iterator iter = names.terator();iter.hasNext();){
String name = (String)iter.next();
System.out.println(name);
}
session.close();
System.out.println(“------------------------------------------”);
………
Query query = session.createQuery(“select s.name from Student s”);
//啟用查詢(xún)緩存
query.setCacheable(true);
List names = query.list();
for(Iterator iter = names.terator();iter.hasNext();){
String name = (String)iter.next();
System.out.println(name);
}
第二次沒(méi)有去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)椴樵?xún)緩存生命周期與session生命周期無(wú)關(guān)
三. 開(kāi)啟查詢(xún)緩存,關(guān)閉二級(jí)緩存,開(kāi)啟兩個(gè)session,分別調(diào)用query.iterate (查詢(xún)屬性)
Query query = session.createQuery(“select s.name from Student s”);
//啟用查詢(xún)緩存
query.setCacheable(true);
for(Iterator iter =query.iterate();iter.hasNext();){
String name = (String)iter.next();
System.out.println(name);
}
session.close();
System.out.println(“------------------------------------------”);
………
Query query = session.createQuery(“select s.name from Student s”);
//啟用查詢(xún)緩存
query.setCacheable(true);
for(Iterator iter = query.iterate();iter.hasNext();){
String name = (String)iter.next();
System.out.println(name);
}
第二去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)椴樵?xún)緩存只對(duì)query.list()起作用,對(duì)query.iterate()不起作用,也就是說(shuō)query.iterate()不使用查詢(xún)緩存
四. 關(guān)閉查詢(xún)緩存,關(guān)閉二級(jí)緩存,開(kāi)啟兩個(gè)session,分別調(diào)用query.list (查詢(xún)實(shí)體對(duì)象)
Query query = session.createQuery(“ from Student s”);
//query.setCacheable(true);
List students = query.list();
for(Iterator iter = students.iterate();iter.hasNext();){
Student stu = (Student)iter.next();
System.out.println(stu.getName());
}
session.close();
System.out.println(“------------------------------------------”);
………
Query query = session.createQuery(“ from Student s”);
//query.setCacheable(true);
List students = query.list();
for(Iterator iter = students.iterate();iter.hasNext();){
Student stu = (Student)iter.next();
System.out.println(stu.getName());
}
第二去查詢(xún)數(shù)據(jù)庫(kù),因?yàn)閘ist默認(rèn)每次都會(huì)發(fā)出查詢(xún)sql
五. 開(kāi)啟查詢(xún)緩存,關(guān)閉二級(jí)緩存,開(kāi)啟兩個(gè)session,分別調(diào)用query.list (查詢(xún)實(shí)體對(duì)象)
Query query = session.createQuery(“ from Student s”);
query.setCacheable(true);
List students = query.list();
for(Iterator iter = students.iterate();iter.hasNext();){
Student stu = (Student)iter.next();
System.out.println(stu.getName());
}
session.close();
System.out.println(“------------------------------------------”);
………
Query query = session.createQuery(“ from Student s”);
query.setCacheable(true);
List students = query.list();
for(Iterator iter = students.iterate();iter.hasNext();){
Student stu = (Student)iter.next();
System.out.println(stu.getName());
}
第二去查詢(xún)數(shù)據(jù)庫(kù)時(shí),會(huì)發(fā)出N條sql語(yǔ)句,因?yàn)殚_(kāi)啟了查詢(xún)緩存,關(guān)閉了二級(jí)緩存,那么查詢(xún)緩存會(huì)緩存實(shí)體對(duì)象的id,所以hibernate會(huì)根據(jù)實(shí)體對(duì)象的id去查詢(xún)相應(yīng)的實(shí)體,如果緩存中不存在相應(yīng)的實(shí)體,那么將發(fā)出根據(jù)實(shí)體id查詢(xún)的sql語(yǔ)句,否則不會(huì)發(fā)出sql,使用緩存中的數(shù)據(jù)
六. 開(kāi)啟查詢(xún)緩存,開(kāi)啟二級(jí)緩存,開(kāi)啟兩個(gè)session,分別調(diào)用query.list (查詢(xún)實(shí)體對(duì)象)
Query query = session.createQuery(“ from Student s”);
query.setCacheable(true);
List students = query.list();
for(Iterator iter = students.iterate();iter.hasNext();){
Student stu = (Student)iter.next();
System.out.println(stu.getName());
}
session.close();
System.out.println(“------------------------------------------”);
………
Query query = session.createQuery(“ from Student s”);
query.setCacheable(true);
List students = query.list();
for(Iterator iter = students.iterate();iter.hasNext();){
Student stu = (Student)iter.next();
System.out.println(stu.getName());
}
第二不會(huì)發(fā)出sql,因?yàn)殚_(kāi)啟了二級(jí)緩存和查詢(xún)緩存,查詢(xún)緩存緩存了實(shí)體對(duì)象的id列表,hibernate會(huì)根據(jù)實(shí)體對(duì)象的id列表到二級(jí)緩存中取得相應(yīng)的數(shù)據(jù)
柳德才
13691193654
18942949207
QQ:422157370
liudecai_zan@126.com湖北-武漢-江夏-廟山