国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

hibernate查漏補缺3

2019-11-14 22:01:56
字體:
來源:轉載
供稿:網友
hibernate查漏補缺3

hibernate的檢索策略

轉載請注明: TheViperhttp://m.survivalescaperooms.com/TheViper

先看個大概

1.類級別

立即檢索 <class lazy='false'>;延遲檢索<class lazy='true'>.默認為延遲檢索。

如果加載一個持久化對象是為了獲取它的屬性,用立即檢索;而如果僅僅是為了獲取它的引用,用延遲加載。比如,

    Friend_Category fc = new Friend_Category();        fc.setCategory_name("已經存在的好友分類");        User_Friend_pk pk = new User_Friend_pk();        pk.setFriend_name(“新好友”);        pk.setName("TheViper");        User_Friend uf = new User_Friend();        uf.setUser_friend_pk(pk);        Friend_Category fc1 = (Friend_Category) session.load(                Friend_Category.class, 1);        uf.setFriend_categorys(fc1);        // uf.setSort("好基友");        session.saveOrUpdate(fc1);        session.save(uf);

可以看到,加載Friend_Catagory類只是為了把新加好友加入到已經存在的好友分類里。這里用load()返回一個代理類,里面只有id屬性,其他屬性均為null,并沒有返回所有的屬性,因此占用的內存很少。

另外,不管<class> 的lazy屬性是true還是false,get(),list()總是用立即加載,但是并不會去加載與之相關聯的類(關聯級別檢索為默認設置延遲加載)。

2.關聯級別

  • 一對多和多對多關聯的檢索策略

由<set>的lazy和fetch屬性決定

lazy:決定關聯集合被初始化的時機。即是在加載時就被初始化,還是在被訪問時才初始化。

fetch:取值為select或subselect時,決定初始化關聯集合時查詢語句的形式;取值為fetch時,決定關聯集合被初始化的時機,這時顯式設置lazy屬性是無意義的。

lazy=true時,關聯集合類的代理在下面情況會被初始化:

1.應用程序第一次訪問它,如調用它的iterator(),size(),isEmpty()或contains().

2.通過org.hibernate.Hibernate類的initialize()靜態方法初始化。

對于lazy=extra,hibernate會進一步延遲關聯對象的初始化時機。具體說就是僅當應用程序第一次調用關聯對象的iterator()時才會加載。只有這一個方法能起作用。

對于lazy=false,

Feeling f = (Feeling) session.get(Feeling.class, 1);
        <set name="feelingComments" inverse="true" lazy="false">            <key column="feeling_id" />            <one-to-many class="model.FeelingComment" />        </set>

當取出Feeling類時,便會一并取出FeelingComment類

Hibernate:     select        feeling0_.feeling_id  as feeling1_1_0_,        feeling0_.content as content1_0_,        feeling0_.id as id1_0_     from        feeling feeling0_     where        feeling0_.feeling_id =?Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?

下面設置fetch=subselect,

        Session session = sf.openSession();        Transaction transaction = session.beginTransaction();        Query q = session.createQuery("from Feeling feeling");        List<Feeling> feelings = (List<Feeling>) q.list();        for (Feeling feeling : feelings) {            Set comments = feeling.getFeelingComments();            System.out.PRintln(comments);        }        transaction.commit();        session.close();
Hibernate:     select        feeling0_.feeling_id  as feeling1_1_,        feeling0_.content as content1_,        feeling0_.id as id1_     from        feeling feeling0_Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id in (            select                feeling0_.feeling_id              from                feeling feeling0_        )[model.FeelingComment@17f2fe3, model.FeelingComment@1211a4b, model.FeelingComment@533fc3][model.FeelingComment@a9a994, model.FeelingComment@455d96][model.FeelingComment@35c6f]

可以看到hibernate是用in子查詢的方式抓取關聯對象的,這時batch-size屬性會被忽略。

fetch=join表示采用左外連接的檢索策略抓取關聯對象,注意list()會自動忽略這個設置,這個很重要。

還是上面的代碼,結果

Hibernate:     select        feeling0_.feeling_id  as feeling1_1_,        feeling0_.content as content1_,        feeling0_.id as id1_     from        feeling feeling0_Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?[model.FeelingComment@1fbf047, model.FeelingComment@82a092, model.FeelingComment@15bd7c5]Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?[model.FeelingComment@c407e, model.FeelingComment@5e3212]Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?[model.FeelingComment@69757f]

而這時設置lazy,batch-size屬性沒有意義。

關于batch-size屬性,它用來為檢索策略設定批量檢索的數量,可以減少select語句的數量,提供檢索的運行性能。

比如batch-size設為2,關聯集合里面有3個對象。

        Session session = sf.openSession();        Transaction transaction = session.beginTransaction();        Query q = session.createQuery("from Feeling feeling");        List<Feeling> feelings = (List<Feeling>) q.list();        for (Feeling feeling : feelings) {            Set comments = feeling.getFeelingComments();            System.out.println(comments);        }        transaction.commit();        session.close();
Hibernate:     select        feeling0_.feeling_id  as feeling1_1_,        feeling0_.content as content1_,        feeling0_.id as id1_     from        feeling feeling0_Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id in (            ?, ?        )[model.FeelingComment@177151, model.FeelingComment@16e125, model.FeelingComment@110a0ca]Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?[model.FeelingComment@1c8f247, model.FeelingComment@1d67998][model.FeelingComment@ac44e3]

注意,如果對Query接口用iterator()返回數據的話,會忽略batch-size!

Hibernate:     select        feeling0_.feeling_id  as col_0_0_     from        feeling feeling0_Hibernate:     select        feeling0_.feeling_id  as feeling1_1_0_,        feeling0_.content as content1_0_,        feeling0_.id as id1_0_     from        feeling feeling0_     where        feeling0_.feeling_id =?Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?[model.FeelingComment@ee7d2a, model.FeelingComment@fb3758, model.FeelingComment@17596bc]Hibernate:     select        feeling0_.feeling_id  as feeling1_1_0_,        feeling0_.content as content1_0_,        feeling0_.id as id1_0_     from        feeling feeling0_     where        feeling0_.feeling_id =?Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?[model.FeelingComment@855e17]Hibernate:     select        feeling0_.feeling_id  as feeling1_1_0_,        feeling0_.content as content1_0_,        feeling0_.id as id1_0_     from        feeling feeling0_     where        feeling0_.feeling_id =?Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?[model.FeelingComment@85ba73, model.FeelingComment@191bae7]

iterator()參見上一篇說明.

  • 多對一和一對一關聯的檢索策略

fetch=join

        <set name="feelingComments" inverse="true">            <key column="feeling_id" />            <one-to-many class="model.FeelingComment" />        </set>
        <many-to-one name="feelings" column="feeling_id" class="model.Feeling"            not-null="false" fetch="join">        </many-to-one>
        FeelingComment f = (FeelingComment) session                .get(FeelingComment.class, 1);
Hibernate:     select        feelingcom0_.feelingComment_id  as feelingC1_2_1_,        feelingcom0_.content as content2_1_,        feelingcom0_.feeling_id as feeling3_2_1_,        feelingcom0_.id as id2_1_,        feeling1_.feeling_id  as feeling1_1_0_,        feeling1_.content as content1_0_,        feeling1_.id as id1_0_     from        feeling_comment feelingcom0_     left outer join        feeling feeling1_             on feelingcom0_.feeling_id=feeling1_.feeling_id      where        feelingcom0_.feelingComment_id =?

上面的很簡單。稍微變一下,在<set>添加lazy=false.

Hibernate:     select        feelingcom0_.feelingComment_id  as feelingC1_2_1_,        feelingcom0_.content as content2_1_,        feelingcom0_.feeling_id as feeling3_2_1_,        feelingcom0_.id as id2_1_,        feeling1_.feeling_id  as feeling1_1_0_,        feeling1_.content as content1_0_,        feeling1_.id as id1_0_     from        feeling_comment feelingcom0_     left outer join        feeling feeling1_             on feelingcom0_.feeling_id=feeling1_.feeling_id      where        feelingcom0_.feelingComment_id =?Hibernate:     select        feelingcom0_.feeling_id as feeling3_1_1_,        feelingcom0_.feelingComment_id  as feelingC1_1_,        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feeling_id=?

可以看到,這次發出了兩條sql,第二次會再次根據feeling_id取出feeling_comment,個人感覺沒意義啊。而在一對多和多對多中就不會出現這種情況。

另外,list()也會像一對多和多對多,忽略fetch=join.

lazy=proxy(默認)

這個像一對多和多對多里面的lazy=true.即查詢“多”那邊時,不會查詢“一”那邊的關聯對象。只有當實際要用關聯對象時才會初始化它。

注意對于<one-to-one>,必須要設置constrained=true.表明“一”那邊的關聯對象不能為空。

lazy=no-proxy

這個和lazy=proxy很相似。不過需要編譯時字節碼增強,否則和proxy沒區別 。

這樣做了后的效果。

        FeelingComment f = (FeelingComment) session                .get(FeelingComment.class, 1);        Feeling f1 = f.getFeelings();        f1.getContent();

當運行到getFeelings()時,hibernate會發出sql.而lazy=proxy時,要運行到getContent()時才發出。

lazy=false

當運行到get()時就會發出兩條sql.

Hibernate:     select        feelingcom0_.feelingComment_id  as feelingC1_2_0_,        feelingcom0_.content as content2_0_,        feelingcom0_.feeling_id as feeling3_2_0_,        feelingcom0_.id as id2_0_     from        feeling_comment feelingcom0_     where        feelingcom0_.feelingComment_id =?Hibernate:     select        feeling0_.feeling_id  as feeling1_1_0_,        feeling0_.content as content1_0_,        feeling0_.id as id1_0_     from        feeling feeling0_     where        feeling0_.feeling_id =?

另外如果

        <many-to-one name="feelings" column="feeling_id" class="model.Feeling"            not-null="false" lazy="false">

同時在“一”那邊

    <class name="model.Feeling" table="feeling" lazy="false">    </class>

便會出現和fetch=join一樣的sql.

        FeelingComment f = (FeelingComment) session                .get(FeelingComment.class, 1);
Hibernate:     select        feelingcom0_.feelingComment_id  as feelingC1_2_1_,        feelingcom0_.content as content2_1_,        feelingcom0_.feeling_id as feeling3_2_1_,        feelingcom0_.id as id2_1_,        feeling1_.feeling_id  as feeling1_1_0_,        feeling1_.content as content1_0_,        feeling1_.id as id1_0_     from        feeling_comment feelingcom0_     left outer join        feeling feeling1_             on feelingcom0_.feeling_id=feeling1_.feeling_id      where        feelingcom0_.feelingComment_id =?

在多對一和一對一中使用批量檢索

在<many-to-one>,<one-to-one>中沒有batch-size屬性,需要“一”那邊設置batch-size.比如,需要加裝三個關聯實例(一),batch-size=2.

    <class name="model.Feeling" table="feeling" batch-size="2">    </class>
        Query q = session.createQuery("from FeelingComment");        List<FeelingComment> feelings = (List<FeelingComment>) q.list();        for (FeelingComment feelingComment : feelings) {            Feeling feeling = feelingComment.getFeelings();            System.out.println(feeling);        }
Hibernate:     select        feelingcom0_.feelingComment_id  as feelingC1_2_,        feelingcom0_.content as content2_,        feelingcom0_.feeling_id as feeling3_2_,        feelingcom0_.id as id2_     from        feeling_comment feelingcom0_Hibernate:     select        feeling0_.feeling_id  as feeling1_1_0_,        feeling0_.content as content1_0_,        feeling0_.id as id1_0_     from        feeling feeling0_     where        feeling0_.feeling_id  in (            ?, ?        )model.Feeling@1e684bdmodel.Feeling@1e684bdmodel.Feeling@1e684bdmodel.Feeling@1149b6cHibernate:     select        feeling0_.feeling_id  as feeling1_1_0_,        feeling0_.content as content1_0_,        feeling0_.id as id1_0_     from        feeling feeling0_     where        feeling0_.feeling_id =?model.Feeling@fb8996model.Feeling@1149b6c

注意上面的例子<many-to-one>中的lazy是默認的proxy.如果lazy=false的話,當運行到feelingComment.getFeelings();時就會發出后面的sql了。

  • 屬性級別的檢索策略

只需在<property>,<component>上設置lazy=true.這種策略適用于二進制大對象,字符串大對象,大容量組件類型的屬性。比如User類的image屬性儲存著圖片的二進制數據,

User user=(User)session.get(User.class,1);user.getImage();

get()時,hibernate沒有加載image屬性,運行到getImage()時才會加載。

注意,用的時候必須向多對一,一對一lazy=no-proxy一樣,需要編譯時字節碼增強。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 九寨沟县| 荔波县| 奉化市| 开江县| 鄂尔多斯市| 佛山市| 淅川县| 望都县| 平乐县| 沙雅县| 曲阳县| 高雄县| 宁蒗| 苏尼特左旗| 常山县| 吉隆县| 个旧市| 和硕县| 拉萨市| 广丰县| 凤城市| 大新县| 鹤峰县| 七台河市| 大安市| 阳东县| 通州市| 广汉市| 旌德县| 昭平县| 师宗县| 德昌县| 上思县| 宁波市| 南丰县| 长子县| 宜城市| 浮山县| 成都市| 镇宁| 玉屏|