package com.hibernate.higherApplication;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Expression;
public class DurationOperator extends TestCase {
private SessionFactory sessionFactory = null;
private Session session = null;
/**
* 初始化資源
*/
protected void setUp() throws Exception {
try {
//加載類(lèi)路徑下的hibernate.cfg.xml文件
Configuration config = new Configuration().configure();
//創(chuàng)建sessionFactory對(duì)象
sessionFactory = config.buildSessionFactory();
//創(chuàng)建session
session = sessionFactory.openSession();
} catch (HibernateException e) {
e.printStackTrace();
}
}
/**
* load/get方法均可以根據(jù)指定的實(shí)體類(lèi)和id從數(shù)據(jù)庫(kù)讀取記錄,并返回與之對(duì)應(yīng)的實(shí)體對(duì)象。
* 區(qū)別在于:
* 1、如果未發(fā)現(xiàn)符合條件的記錄,get方法返回null,而load方法拋出一個(gè)ObjectNotFoundException
* 2、load方法可以返回實(shí)體的代理類(lèi)實(shí)例,而get方法永遠(yuǎn)直接返回實(shí)體類(lèi)。
* 3、load方法可以充分利用內(nèi)部緩存和二級(jí)緩存中的現(xiàn)有數(shù)據(jù),而get方法則僅僅在內(nèi)部緩存中進(jìn)行數(shù)據(jù)查找,如果
* 沒(méi)有發(fā)現(xiàn)數(shù)據(jù),將越過(guò)二級(jí)緩存,直接調(diào)用SQL完成數(shù)據(jù)讀取。
*
*/
public void loadOrGetData(){
TUser user = (TUser)session.load(TUser.class,new Integer(1));
}
/**
* 查詢(xún)性能往往是一系統(tǒng)性能表現(xiàn)的一個(gè)重要方面。
* query.list方法通過(guò)一條select SQL實(shí)現(xiàn)了查詢(xún)操作,而iterate方法,則執(zhí)行了3次selectSQL,第一次獲取了所有符合條件的記錄
* 的id,之后,在根據(jù)各個(gè)id從庫(kù)表中讀取對(duì)應(yīng)的哦記錄,這是一個(gè)典型的N+1次查詢(xún)問(wèn)題。
*
* 我們進(jìn)行query.list數(shù)據(jù)查詢(xún)時(shí),即使緩存中已經(jīng)有一些符合條件的實(shí)體對(duì)象存在,我們也無(wú)法保證這些數(shù)據(jù)就是庫(kù)表中所有符合條件的數(shù)據(jù)。假設(shè)
* 第一次查詢(xún)條件是age>25,隨即緩存中就包括了所有age>25的user數(shù)據(jù);第二次查詢(xún)條件為age>20,此時(shí)緩存中雖然包含了滿(mǎn)足age>25d的
* 數(shù)據(jù),但這些并不是滿(mǎn)足條件age>20的全部數(shù)據(jù)
* 因此,query.list方法還是需要執(zhí)行一次select sql以保證查詢(xún)結(jié)果的完整性(iterate方法通過(guò)首先查詢(xún)獲取所有符合條件記錄的id,以此保證
* 查詢(xún)結(jié)果的完整性)。
* 因此,query.list方法實(shí)際上無(wú)法利用緩存,它對(duì)緩存只寫(xiě)不讀。而iterate方法則可以充分發(fā)揮緩存帶來(lái)的優(yōu)勢(shì),如果目標(biāo)數(shù)據(jù)只讀或者讀取相對(duì)
* 較為頻繁,通過(guò)這種機(jī)制可以大大減少性能上的損耗。
*/
public void queryForList(){
String hql = "from TUser where age>?";
Query query = session.createQuery(hql);
query.setInteger(1,1);
List list = query.list();
for(int i=0;i<list.size();i++){
TUser user = (TUser)list.get(i);
System.out.println("User age:"+user.getAge());
}
}
public void queryForIterate(){
String hql = "from TUser where age>?";
Query query = session.createQuery(hql);
query.setInteger(1,1);
Iterator it = query.iterate();
while(it.hasNext()){
TUser user = (TUser)it.next();
System.out.println("User age:"+user.getAge());
}
}
/**
* 大數(shù)據(jù)量的批量讀取(10W條)
* 解決方案:結(jié)合iterate方法和evict方法逐條對(duì)記錄進(jìn)行處理,將內(nèi)存消耗保持在可以接受的范圍之內(nèi)。
* 在實(shí)際開(kāi)發(fā)中,對(duì)于大批量數(shù)據(jù)處理,還是推薦采用SQL或存儲(chǔ)過(guò)程實(shí)現(xiàn),以獲得較高的性能,并保證系統(tǒng)平滑運(yùn)行。
*/
public void bigDataRead(){
String hql = "from TUser where age>?";
Query query = session.createQuery(hql);
query.setInteger("age", 1);
Iterator it = query.iterate();
while(it.hasNext()){
TUser user = (TUser)it.next();
//將對(duì)象從一級(jí)緩存中移除
session.evict(user);
//二級(jí)緩存可以設(shè)定最大數(shù)據(jù)緩存數(shù)量,達(dá)到峰值時(shí)會(huì)自動(dòng)對(duì)緩存中的較老數(shù)據(jù)進(jìn)行廢除,但是我們這里還是通過(guò)
//編碼指定將對(duì)象從二級(jí)緩存中移除,這有助保持緩存的數(shù)據(jù)有效性。
sessionFactory.evict(TUser.class,user.getId());
}
}
/**
* Query Cache彌補(bǔ)了find方法的不足,QueryCache中緩存的SQL及其結(jié)果及并非永遠(yuǎn)存在,當(dāng)Hibernate發(fā)現(xiàn)此SQL對(duì)應(yīng)的庫(kù)表發(fā)生變動(dòng),
* 會(huì)自動(dòng)將Query Cache中對(duì)應(yīng)表的SQL緩存廢除。因此Query Cache只在特定的情況下產(chǎn)生作用:
* 1、完全相同的select SQL重復(fù)執(zhí)行。
* 2、在2次查詢(xún)之間,此select SQL對(duì)應(yīng)的庫(kù)表沒(méi)有發(fā)生過(guò)改變。
*/
public void queryForQueryCache(){
String hql = "from TUser where age>?";
Query query = session.createQuery(hql);
query.setInteger(1, 1);
//除了在這里設(shè)置QueryCache外,還要在hibernate.cfg.xml中進(jìn)行設(shè)置
//<property name="hibernate.cache.use_query_cache">true</property>
query.setCacheable(true);
List userList = query.list();
}
/**
* 所謂延遲加載,就是在需要數(shù)據(jù)的時(shí)候,才真正執(zhí)行數(shù)據(jù)加載操作。
* 延遲加載實(shí)現(xiàn)主要針對(duì):
* 1、實(shí)體對(duì)象:通過(guò)class的lazy屬性,我們可以打開(kāi)實(shí)體對(duì)象的延遲加載功能。
* 2、集合
*/
public void queryForEntityLazy(){
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("name","Erica"));
List userList = criteria.list();
TUser user = (TUser)userList.get(0);
//雖然使用了延遲加載,但是我們可以通過(guò)hibernate的初始化方法進(jìn)行強(qiáng)制加載,這樣即使session關(guān)閉之后,關(guān)聯(lián)的對(duì)象仍讓可以使用
Hibernate.initialize(user.getAddresses());
System.out.println("User name=>"+user.getAge());
Set hset =user.getAddresses();
TAddresses addr = (TAddresses)hset.toArray()[0];
System.out.println(addr.getAddress());
session.close();
}
/**
* 關(guān)閉資源
*/
protected void tearDown() throws Exception {
try{
session.close();
}catch(HibernateException e){
e.printStackTrace();
}
}
}
posted on 2010-01-02 15:27
王永慶 閱讀(363)
評(píng)論(0) 編輯 收藏 所屬分類(lèi):
HIBERNATE