Проблемы с удалением объектов в Grails - медленные, но до сих пор не очень удалены - PullRequest
1 голос
/ 11 августа 2011

Это, вероятно, ошибка новичка, так что прости меня заранее. Я искал решение проблемы, но безрезультатно - поэтому я решил добавить свой первый пост здесь: -)

У меня есть два класса домена, один называется Домен, а другой - Страница. Как показано в приведенном ниже коде, Домен имеет много страниц.

class Domain {
          ...
    static hasMany = [  pages : Page, ... ]
    static mapping = {
        pages lazy:true
    }
}

class Page {
    String identifier
    ...
    static belongsTo = [ domain : Domain ]
    static hasMany = [ ... ]
    static constraints = {
        identifier(blank:false, unique:'domain')
    }
    static mapping = {
        ...
        domain lazy:true
    }
}

Мое приложение имеет длинный алгоритм, который, помимо прочего, создает страницы в домене. Если вы запустите алгоритм с теми же аргументами, что и при предыдущем запуске, он начнется с удаления всех страниц, созданных в предыдущем запуске, перед повторным запуском алгоритма.

У меня две проблемы:

Задача № 1 Когда я удаляю определенную страницу из домена, используя:

def domain = page.domain
domain.removeFromPages(page);
page.delete()
domain.save(flush:true)

Это приводит к тому, что Hibernate извлекает и загружает все страницы домена, что в итоге запускает несколько тысяч запросов (домен имеет МНОГО страниц). Как я могу улучшить производительность на этом? - Выполнение sql напрямую для удаления страницы приводит к потере синхронизации базы данных и гибернации.

Задача № 2 Когда я позже снова создам страницу:

def page = new Page(identifier:'...').save(failOnError:true)

Я получаю:

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

Любая помощь приветствуется - я схожу с ума здесь: - /

Ответы [ 2 ]

1 голос
/ 11 августа 2011

Я бы предложил подумать о небольшом редизайне ваших классов.Сначала удалите коллекцию страниц из «Домена»

Class Domain {
  // no pages here
}

А затем поместите простую ссылку на «Домен» в «Странице»

Class Page {    
    String identifier
    Domain domain
    ...
}

Это сделает обработку ваших страницнамного легче.Я не знаю, действительно ли это вариант для вас, потому что вы должны внести изменения в существующий код, но это может избавить вас от многих проблем с большими коллекциями.Об этом есть также презентация Берта Беквита .

0 голосов
/ 11 августа 2011

Пакетное удаление см. В этом сообщении IntelliGrape

Мне нужно было выбрать и сохранить праздники, хранящиеся в удаленной системе, и при каждой выборке удалять те, которые я хранил локально, и это выглядело так:

Holiday.list()*.delete(flush:true)

* Здесь происходит вся магия. Обратите внимание, что вы можете ограничить количество удаляемых элементов с помощью метода list ().

Обратите внимание, что в пакете вы также можете использовать следующее для выполнения пакета.

def session = sessionFactory.openSession()
def tx = session.beginTransaction()

... 
for(holiday in holidays) {
        def h = new Holiday(..)
        session.save(h) 
}
sessionFactory.currentSession.flush()
tx.commit()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...