2013-06-08 3 views
0

В приложении Grails, у меня есть отношения, которые по умолчанию ленивых:Hibernate Один-ко-многим ассоциации: подвыборки или нетерпеливого

class Author{ 
    String name 
    static mapping = { 
     books lazy:false 
    } 
} 

У меня есть запрос API критериев, который извлекает авторов. Когда я выполнить запрос

Author.createCriteria().list{ 
    eq("name", "John") 
} 

я есть N + 1 подзапросы для каждого автора.

Мой второй подход к стремится принести книги так же, как это:

Author.createCriteria().list{ 
    eq("name", "John") 
    fetchMode("books", FetchMode.JOIN) 
} 

В этом случае N + 1 выберите проблема не появляется, однако у меня есть JOIN запрос.

Какой подход лучше с точки зрения производительности и оптимизации?

ответ

0

Я думаю, вы имели в виду по умолчанию eager вместо lazy в первой строке вопроса.

POINT ПОМНИТЬ
Когда ассоциации включены в критерии запроса, они по умолчанию усердия неправдоподобным.

В вашем случае вам не нужно отображать books lazy:false в Author.
С точки зрения оптимизации я бы ручаться за ниже подхода:

class Author { 
    String name 
    static hasMany = [books: Book] 
    static mapping = { 
     //books lazy:false (DO NOT NEED) 
    } 
} 

class Book { 
    String bookName 
    //set belongsTo if you need bi-directional one-many 
    //books gets cascade deleted when author is deleted 
    //static belongsTo = [author: Author] 
} 

//Bootstrap 
def author1 = new Author(name: "Dan Brown") 
def book1 = new Book(bookName: "Da Vinci Code") 
def book2 = new Book(bookName: "Angels And Demons") 
def book3 = new Book(bookName: "Inferno") 

[book1, book2, book3].each {author1.addToBooks(it)} 
author1.save(flush: true, failOnError: true) 

//Criteria 
Author.createCriteria().list{ 
    eq("name", "Dan Brown") 
    books{ 
     //books are eagerly fetched by default using inner join. No need to specify FetchMode. 
    } 
} 

С точки зрения производительности я бы не идти с вышеизложенным подходом, если я каждый автор, который написал 20000 блогов (заменить книги с блогами). С нетерпением собираются 20000 блогов для n авторов будут хитом производительности. В этом случае я бы пошел на ленивый выбор (N + 1) и попытался отфильтровать блоги в соответствии с моим требованием. Что-то, как показано ниже:

def author = Author.findByName("Dan Brown") 
def books = author.books 
//Assume you have a field publishedYear in Book 
def booksReleasedIn2013 = author.books.findAll{it.publishedYear == 2013} 
def booksReleasedBefore2013 = author.books.findAll{it.publishedYear < 2013} 

assert "Inferno" in booksReleasedIn2013*.bookName 
assert "Angels And Demons" in booksReleasedBefore2013*.bookName 

Если у вас нет такого (блог случая) случая, то я хотел бы использовать пример, приведенный выше для обоих оптимизации и производительности.