2009-09-02 16 views
2

各書籍には多くの著者がいます。そして各著者は多くの本を執筆することができます。多対多の関係を持つEager Loading - Grails(GORM)

class Book { 
    static belongsTo = Author 
    static hasMany = [authors:Author] 
} 

class Author { 
    static hasMany = [books:Book] 
} 

は今、私は時に操作を行うことができます。

def book = Book.get(id) 
def authors = book.authors 

は、今私は、私はそれぞれの作者を取り、彼が関連付けられている本を得ることができる必要があります考えています:

authors.each { 
    it.books 
} 

あなたが見ます今度は再帰的になります(スタックオーバーフローにつながります)。熱心なフェッチをしているとき、どのように正確に動作するかを知っていますか?

答えて

1

Hibernateで管理されたインスタンスがロードされると、それは第1レベルのキャッシュであるHibernateセッションに保持されます(2次キャッシュも設定している場合はインスタンスも存在します)。彼らが以前にロードされていた場合、そこから来ている可能性があります)。

ブックをロードしてから、著者のコレクション(デフォルトでは「セット」)を読み込んだので、各著者の書籍はすでにセッションに入っているので、データベースに行く必要はありません。

マップされたコレクションを読み込むと、最初のResultSetを使用して、トップレベルのインスタンスと1つのデータベースクエリの子インスタンスを取得します。そのコレクションを遅延ロードするには、コレクションにデータを格納するための2番目のデータベースクエリが必要ですが、必要に応じてコレクションをロードするだけの利点があります。

+0

私はBook1を熱心に読み込むと、Book1のすべての著者、例えばAuthor1、Author2など、したがってそれらの著者のそれぞれが書いたすべての本もセッションにロードされます。そうですか? – Langali

+1

GrailsがHibernateがサポートする「最大フェッチ深度」をどのように設定するのかよく分かりませんが、確か2つのクラスでうまくいくはずです。書籍の著者と著者の本の両方についてeager fetchingを指定すると、すべてが読み込まれます。これは潜在的に高価です - あなたが多くの本を書く作者によって書かれた本を読み込むなら、両方のテーブルのすべての要素を読み込むのにはあまり時間がかかりません。インスタンスをロードするたびに子コレクションのすべてのインスタンスを必要としないことが多いため、Eagerローディングはほとんど使用しないでください。 –

1

さらに明確にするために、Burt Beckwithによって書かれたブログhttp://burtbeckwith.com/blog/?p=169を参照してください。また、ブログにあるプレゼンテーションリンクを参照することもできます。