shinewang

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            53 隨筆 :: 0 文章 :: 200 評論 :: 0 Trackbacks

          使用ORM時,常常碰到N+1次查詢的問題。Hibernate采用立即加載(eager load)和延遲加載(lazy load)來解決這一問題,GROM建立在Hibernate的基礎(chǔ)之上,理論上同樣適用。但事實如何?

          Grails的官方文檔中提到:默認情況下,GORM 集合使用延遲加載的并且可以通過fetchMode來配置或者是使用mapping來配置 。并給出了一段在domain中配置的樣例代碼。

          但從我的使用經(jīng)驗來看,不推薦在domain類中配置延遲加載。原因如下:
          1、在domain類中配置延遲加載是全局性的,有可能造成不需要開銷。
          2、目前在domain類中配置延遲加載存在Bug,只對one-to-many的關(guān)系才有效。

          例如論壇的列表頁面,需要顯示topic的分頁列表,其中每條topic需要顯示作者的名字,topic最后回復(fù)帖子的作者。

          按照官方文檔,可以在Topic類中如下配置,查詢結(jié)果為1條topic,理論上結(jié)果應(yīng)該執(zhí)行一條SQL語句:

          class ?Topic? {
          ????String?title
          ????String?body
          ????Date?createTime?
          = ? new ?Date()
          ????User?author
          ????Integer?viewNum?
          = ? 0
          ????Integer?postNum?
          = ? 0
          ????Date?lastUpdateTime
          ????User?lastUpdateBy
          ????
          static ?hasMany? = ?[?posts?:?Post?]
          ????
          static ?fetchMode? = ?[author: ' eager ' ,?lastUpdateBy: ' eager ' ]
          }

          但從SQL Log來看,Grails還是執(zhí)行了3條SQL:

          select ?? from ?topic? where ?id = ?
          select ?? from ? user ? where ?id = ?
          select ?? from ? user ? where ?id = ?

          也就是說在domain類中配置延遲加載存在對one-to-one, many-to-one是無效的。

          如果這樣配置:

          class ?Topic? {
          ????String?title
          ????String?body
          ????Date?createTime?
          = ? new ?Date()
          ????User?author
          ????Integer?viewNum?
          = ? 0
          ????Integer?postNum?
          = ? 0
          ????Date?lastUpdateTime
          ????User?lastUpdateBy
          ????
          static ?hasMany? = ?[?posts?:?Post?]
          ????
          static ?fetchMode? = ?[posts: ' eager ' ]
          }

          執(zhí)行Topic.get(id)來加載1條Topic,執(zhí)行結(jié)果為1條SQL:

          select ?? from ?topic? left ? outer ? join ?post? on ?topic.id = posttopic_id? where ?topic.id = ?

          也就是說在domain類中配置延遲加載存在對one-to-many是有效的。以上結(jié)論對使用mapping來配置也是一樣的。

          這無疑是一個尷尬的結(jié)論,適用全局立即加載的author和lastUpdateBy不能在domain類中通過配置事先,不適用全局立即加載的posts卻可以。看來GROM對Hibernate的包裝還存在問題。

          目前的解決方法是不要在domain類中配置立即加載,而是在取數(shù)據(jù)的方法中按需要配置,例如Topic.list(fetch:[author:'eager', lastUpdateBy:'eager'])

          另外,可以參考一下這里關(guān)于立即加載和N+1次查詢性能的爭論。


          歡迎訪問我的blog: http://www.eoss.cn/blog/

          posted on 2008-11-26 16:06 shinewang 閱讀(2015) 評論(0)  編輯  收藏 所屬分類: Groovy & Grails
          主站蜘蛛池模板: 类乌齐县| 阿荣旗| 泽普县| 怀来县| 英德市| 和政县| 鹿泉市| 同心县| 永寿县| 太康县| 平邑县| 同江市| 大新县| 嘉鱼县| 大石桥市| 灵寿县| 新龙县| 滁州市| 航空| 璧山县| 故城县| 舞阳县| 洛川县| 邯郸县| 峨眉山市| 阜新市| 南雄市| 黄陵县| 延边| 承德县| 鸡东县| 黄冈市| 新密市| 南溪县| 开平市| 崇仁县| 长葛市| 洛宁县| 巴林右旗| 安丘市| 砀山县|