Hibernate的強制載入策略

來源:互聯網
上載者:User

標籤:style   http   java   os   io   檔案   資料   for   

延後載入:

  延後載入機制是號碼大全為了防止一些無謂的功用開支而提出來關鍵詞挖掘工具的,所謂延後載入即是當在真實需求資料的時分,才真實履行資料載入操作。在Hibernate中供給了對實體方針的延後載入以及對調集的延後載入,另外在Hibernate3中還供給了對特點的延後載入。下面咱們就別離介紹這些品種的延後載入的細節。

A、實體方針的延後載入:

 假如想對實體方針運用延後載入,有必要要在實體的映射裝備檔案中進行相應的裝備,如下所示:

?

 

   ……

 

 

經過將class的lazy特點設定為true,來敞開實體的延後載入特性。假如咱們運轉下面的代碼:

User user=(User)session.load(User.class,”1”);(1)

System.out.println(user.getName());(2)

當運轉到(1)處時,Hibernate並沒有建議對資料的查詢,假如咱們此刻經過一些調試東西(比方JBuilder2005的Debug東西),調查此刻user方針的記憶體快照,咱們會驚奇的發現,此刻回來的可能是User$EnhancerByCGLIB$$bede8986類型的方針,並且其特點為null,這是怎麼回事?還記得前面我曾講過session.load()辦法,會回來實體方針的署理類方針,這兒所回來的方針類型即是User方針的署理類方針。在Hibernate中經過運用CGLIB,來完結動態結構一個方針方針的署理類方針,並且在署理類方針中包含方針方針的一切特點和辦法,並且一切特點均被賦值為null。經過調試器顯現的記憶體快照,咱們能夠看出此刻真實的User方針,是包含在署理方針的CGLIB$CALBACK_0.target特點中,當代碼運轉到(2)處時,此刻調用user.getName()辦法,這時經過CGLIB賦予的回調機制,實踐上調用CGLIB$CALBACK_0.getName()辦法,當調用該辦法時,Hibernate會首先查看CGLIB$CALBACK_0.target特點是不是為null,假如不為空白,則調用方針方針的getName辦法,假如為空白,則會建議資料庫查詢,產生相似這樣的SQL句子:select * from user where id=’1’;來查詢資料,並結構方針方針,並且將它賦值到CGLIB$CALBACK_0.target特點中。

   這樣,經過一個中心署理方針,Hibernate完結了實體的延後載入,只要當使用者真實建議獲得實體方針特點的動作時,才真實會建議資料庫查詢操作。所以實體的延後載入是用經過中心署理類完結的,所以只要session.load()辦法才會運用實體延後載入,由於只要session.load()辦法才會回來實體類的署理類方針。

B、調集類型的延後載入:

在Hibernate的延後載入機制中,對於調集類型的運用,含義是最為嚴重的,由於這有可能使功用得到大幅度的提高,為此Hibernate進行了很多的儘力,其間包括對JDK Collection的獨立完結,咱們在一對多相關中,定義的用來容納相關方針的Set調集,並不是java.util.Set類型或其子類型,而是net.sf.hibernate.collection.Set類型,經過運用自訂調集類的完結,Hibernate完結了調集類型的延後載入。為了對調集類型運用延後載入,咱們有必要如下裝備咱們的實體類的對於相關的有些:

 

   

…..

 

 

 

 

   

 

經過將元素的lazy特點設定為true來敞開調集類型的延後載入特性。咱們看下面的代碼:

User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();      (1)

Iterator it=addset.iterator();               (2)

while(it.hasNext()){

 Address address=(Address)it.next();

 System.out.println(address.getAddress());

}

當程式履行到(1)處時,這時並不會建議對相關資料的查詢來載入相關資料,只要運轉到(2)處時,真實的資料讀取操作才會開端,這時Hibernate會依據緩衝中契合條件的資料索引,來尋找契合條件的實體方針。

這兒咱們引入了一個全新的概念——資料索引,下面咱們首先將講一下啥是資料索引。在Hibernate中對調集類型進行緩衝時,是分兩有些進行緩衝的,首先緩衝調集中一切實體的id列表,然後緩衝實體方針,這些實體方針的id列表,即是所謂的資料索引。當尋找資料索引時,假如沒有找到對應的資料索引,這時就會一條select SQL的履行,獲得契合條件的資料,並結構實體方針調集和資料索引,然後回來實體方針的調集,並且將實體方針和資料索引歸入Hibernate的緩衝之中。另一方面,假如找到對應的資料索引,則從資料索引中取出id列表,然後依據id在緩衝中尋找對應的實體,假如找到就從緩衝中回來,假如沒有找到,在建議select SQL查詢。在這兒咱們看出了另外一個疑問,這個疑問可能會對功用產生影響,這即是調集類型的緩衝戰略。假如咱們如下裝備調集類型:

 

   

…..

 

 

 

 

 

   

 

這兒咱們運用了裝備,假如選用這種戰略來裝備調集類型,Hibernate將只會對資料索引進行緩衝,而不會對調集中的實體方針進行緩衝。如上裝備咱們運轉下面的代碼:

User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();      

Iterator it=addset.iterator();               

while(it.hasNext()){

 Address address=(Address)it.next();

 System.out.println(address.getAddress());

}

System.out.println(“Second query……”);

User user2=(User)session.load(User.class,”1”);

Collection it2=user2.getAddresses();

while(it2.hasNext()){

 Address address2=(Address)it2.next();

 System.out.println(address2.getAddress());

}

運轉這段代碼,會得到相似下面的輸出:

Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Select * from address where id=’1’;

Select * from address where id=’2’;

Tianjin

Dalian

咱們看到,當第2次履行查詢時,履行了兩條對address表的查詢操作,為啥會這樣?這是由於當第一次載入實體後,依據調集類型緩衝戰略的裝備,只對調集資料索引進行了緩衝,而並沒有對調集中的實體方針進行緩衝,所以在第2次再次載入實體時,Hibernate找到了對應實體的資料索引,可是依據資料索引,卻無法在緩衝中找到對應的實體,所以Hibernate依據找到的資料索引建議了兩條select SQL的查詢操作,這兒造成了對功用的糟蹋,怎樣才能防止這種狀況呢?咱們有必要對調集類型中的實體也指定緩衝戰略,所以咱們要如下對調集類型進行裝備:

 

   

…..

 

 

 

 

 

   

 

此刻Hibernate會對調集類型中的實體也進行緩衝,假如依據這個裝備再次運轉上面的代碼,將會得到相似如下的輸出:

Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Tianjin

Dalian

這時將不會再有依據資料索引進行查詢的SQL句子,由於此刻能夠直接從緩衝中獲得調集類型中寄存的實體方針。

 

C、特點延後載入:

 在Hibernate3中,引入了一種新的特性——特點的延後載入,這個機制又為擷取高功用查詢供給了有力的東西。在前面咱們講大資料方針讀取時,在User方針中有一個resume欄位,該欄位是一個java.sql.Clob類型,包含了使用者的簡曆資訊,當咱們載入該方針時,咱們不得不每一次都要載入這個欄位,而不論咱們是不是真的需求它,並且這種大資料方針的讀取自身會帶來很大的功用開支。在Hibernate2中,咱們只要經過咱們前面講過的面功用的粒度細分,來分化User類,來解決這個疑問(請參照那一節的論述),可是在Hibernate3中,咱們能夠經過特點延後載入機制,來使咱們獲得只要當咱們真實需求操作這個欄位時,才去讀取這個欄位資料的才能,為此咱們有必要如下裝備咱們的實體類:

 

 

……

 

   

 

經過對元素的lazy特點設定true來敞開特點的延後載入,在Hibernate3中為了完結特點的延後載入,運用了類增強器來對實體類的Class檔案進行強化處置,經過增強器的增強,將CGLIB的回調機制邏輯,參加實體類,這兒咱們能夠看出特點的延後載入,仍是經過CGLIB來完結的。CGLIB是Apache的一個開源工程,這個類庫能夠操作java類的位元組碼,依據位元組碼來動態結構契合要求的類方針。依據上面的裝備咱們運轉下面的代碼:

String sql=”from User user where user.name=’zx’ ”;

Query query=session.createQuery(sql);   (1)

List list=query.list();

for(int i=0;i  User user=(User)list.get(i);

 System.out.println(user.getName());

 System.out.println(user.getResume());   (2)

}

當履行到(1)處時,會產生相似如下的SQL句子:

Select id,age,name from user where name=’zx’;

這時Hibernate會檢索User實體中一切非延後載入特點對應的欄位資料,當履行到(2)處時,會產生相似如下的SQL句子:

Select resume from user where id=’1’;

這時會建議對resume欄位資料真實的讀取操作。

 

---------------------------------

 

延後載入的方針:

hibernate 2對於實體方針和調集

hibernate 3一起供給了特點的延後載入功用。

其間對調集的延後載入特性含義最為嚴重。

實體方針的延後載入:

1.在hibernate裝備檔案中的class指定

 

調集類型的延後載入:

在set中指定lazy=true

這樣只要實踐載入與方針相相關的調集方針的時分,再經過session從資料庫中載入實踐的資料集。

Hibernate.initialize辦法能夠強制Hibernate當即載入相關的方針集,例如:

Hibernate.initialize(user.getAddress());

調集類型的緩衝:

假如為某個調集類設定了緩衝,如

    name="address"

    table="t_address"

    lazy="true"

    ......

>

   

   

   

 

Hibernate對調集類型進行緩衝的時分,分兩有些保留。首先是這個調集中一切實體的id列表,其次才是各個實體方針。

這兒制定了cache usage="read-only"只會使得Hibernate對資料索引進行緩衝。也即是說只緩衝了調集中的資料索引,並不包含調集中的各個實體元素。

假如指定cache usage="read-write"才會對調集中的實體進行緩衝。

 

特點的延後載入:

在property節點中聲明lazy=true,並且還需求憑藉Hibernate類增強器對POJO類的二進位Class檔案進行強化處置。

 

 

hibernate的延後載入通用辦法 

 

 

public class HibernateUtil extends HibernateDaoSupport {

//用法:instance =  getHibernateTemplate().find("from FxjlbVO");

//    super.initialize(instance, "getFxjlbChjs");

    public void initialize(Object object, String methodName)

            throws SecurityException, NoSuchMethodException,

            IllegalArgumentException, IllegalAccessException,

            InvocationTargetException {

 

        String[] methodArray = methodName.split("/.");

        Method method = null;

        Object initializeObject = object;

 

        if (methodArray.length == 1) {

            this.getHibernateTemplate().lock(initializeObject,

                    org.hibernate.LockMode.NONE);

            method = object.getClass()

                    .getMethod(methodArray[0], new Class[] {});

            initializeObject = method.invoke(initializeObject, new Object[] {});

            this.getHibernateTemplate().initialize(initializeObject);

        } else {

            for (int i = 0; i < methodArray.length; i++) {

                method = initializeObject.getClass().getMethod(methodArray[i],

                        new Class[] {});

                initializeObject = method.invoke(initializeObject,

                        new Object[] {});

            }

            this.getHibernateTemplate().lock(initializeObject,

                    org.hibernate.LockMode.NONE);

            this.getHibernateTemplate().initialize(initializeObject);

        }

    }

 

 

    public void initialize(Object object, String methodName[])

            throws SecurityException, NoSuchMethodException,

            IllegalArgumentException, IllegalAccessException,

            InvocationTargetException {

 

        for (int i = 0; i < methodName.length; i++) {

            String[] methodArray = methodName[i].split("/.");

            Method method = null;

            Object initializeObject = object;

 

            if (methodArray.length == 1) {

                this.getHibernateTemplate().lock(initializeObject,

                        org.hibernate.LockMode.NONE);

                

                method = object.getClass().getMethod(methodArray[0],

                        new Class[] {});

                initializeObject = method.invoke(initializeObject,

                        new Object[] {});

                //等價於:initializeObject=PropertyUtils.getProperty(initializeObject,methodArray[0]);

                

                this.getHibernateTemplate().initialize(initializeObject);

            } else {

                for (int j = 0; j < methodArray.length; j++) {

                    method = initializeObject.getClass().getMethod(

                            methodArray[j], new Class[] {});

                    initializeObject = method.invoke(initializeObject,

                            new Object[] {});

                }

                this.getHibernateTemplate().lock(initializeObject,

                        org.hibernate.LockMode.NONE);

                this.getHibernateTemplate().initialize(initializeObject);

            }

        }

 

    }

    // fInitializeFields是調調集,不是辦法名

    //instance =  getHibernateTemplate().find("from FxjlbVO");

    //    HashSet aa=new HashSet();

    //    aa.add("fxjlbChjs");

    //    super.initialize(instance, aa);

    public void initialize(Object object, HashSet fInitializeFields)

            throws SecurityException, NoSuchMethodException,

            IllegalArgumentException, IllegalAccessException,

            InvocationTargetException {

        String[] methodName = new String[fInitializeFields.size()];

        methodName = (String[]) fInitializeFields.toArray(methodName);

        for (int i = 0; i < methodName.length; i++) {

            String[] methodArray = methodName[i].split("/.");

            Method method = null;

-        indexRead arguments from command-line "http://www.shoudashou.com"

-        indexRead arguments from command-line "http://www.4lunwen.cn"

-        indexRead arguments from command-line "http://www.zx1234.cn"

-        indexRead arguments from command-line "http://www.penbar.cn"

-        indexRead arguments from command-line "http://www.whathappy.cn"

-        indexRead arguments from command-line "http://www.lunjin.net"

-        indexRead arguments from command-line "http://www.ssstyle.cn"

-        indexRead arguments from command-line "http://www.91fish.cn"

-        indexRead arguments from command-line "http://www.fanselang.com"

            Object initializeObject = object;

 

            if (methodArray.length == 1) {

                this.getHibernateTemplate().lock(initializeObject,

                        org.hibernate.LockMode.NONE);

                initializeObject=PropertyUtils.getProperty(initializeObject,methodArray[0]);

 

                this.getHibernateTemplate().initialize(initializeObject);

            } else {

                for (int j = 0; j < methodArray.length; j++) {

                initializeObject=PropertyUtils.getProperty(initializeObject,methodArray[0]);

                }

                this.getHibernateTemplate().lock(initializeObject,

                        org.hibernate.LockMode.NONE);

                this.getHibernateTemplate().initialize(initializeObject);

            }

        }

 

    }

    

    public void initialize(Collection collection, HashSet fInitializeFields)

            throws SecurityException, NoSuchMethodException,

            IllegalArgumentException, IllegalAccessException,

            InvocationTargetException {

 

        for (Iterator i = collection.iterator(); i.hasNext();) {

            Object object = i.next();

            this.initialize(object, fInitializeFields);

        }

    }

    

    public void initialize(Object object) throws SecurityException,

            NoSuchMethodException, IllegalArgumentException,

            IllegalAccessException, InvocationTargetException {

        this.getHibernateTemplate().lock(object, org.hibernate.LockMode.NONE);

        this.getHibernateTemplate().initialize(object);

    }

 

 

    public void initialize(Collection collection, String methodName[])

            throws SecurityException, NoSuchMethodException,

            IllegalArgumentException, IllegalAccessException,

            InvocationTargetException {

 

        for (Iterator i = collection.iterator();i.hasNext(); ) {

            Object object = i.next();

            this.initialize(object, methodName);

        }

    }

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.