Пользовательские методы вставки и обновления побеждены автоматическим сохранением - PullRequest
0 голосов
/ 12 октября 2010

Я портирую приложение Grails из Oracle в базу данных MySQL. Первоначальная версия Oracle является устаревшей базой данных, которая использует несколько сложных представлений, использующих функцию Oracle INSTEAD OF INSERT OR UPDATE, которой нет в MySQL. В качестве обходного пути я реализовал методы Insert и Update в классах Domain, которые указывают на эти виды представлений. Например,

class AdminUser {
    //...
    def update() {
        if(this.validate()) {
            Sql sql = Utils.getHibernateSql()

            sql.execute(
                "update table_x ...",
                [...]
            )

            sql.execute(
                "update table_y ...)",
                [...]
            )

            sql.execute(
                "update table_z ...",
                [...]
            )

            return true
        }

        return false
    }
    //...
}

Вот описание проблемы, с которой я сталкиваюсь в данный момент:

  1. В сервисном методе я загружаю экземпляр AdminUser, используя AdminUser.get
  2. Я изменяю загруженный экземпляр и вызываю update (), все выглядит хорошо
  3. Как только сервисный метод завершает выполнение, возникает исключение из-за чего-то, вызывающего save в экземпляре.

Как я могу предотвратить магическое сохранение, происходящее на шаге (3) (я недавно где-то читал, что Grails автоматически сохранит измененный экземпляр класса Domain, который еще не был сохранен при выходе из метода обслуживания, но я не могу показаться чтобы найти ссылку на этот ресурс прямо сейчас)?

Ответы [ 2 ]

2 голосов
/ 12 октября 2010

Вы оставляете измененный экземпляр в сеансе гибернации с грязными полями.Когда сеанс гибернации сбрасывается, он пытается снова сохранить объект с помощью обычного save() метода.

Одним из решений будет удаление вашего объекта из сеанса гибернации после того, как вы вручную сохраните изменения.Например:

def update() {
    if(this.validate()) {
        Sql sql = Utils.getHibernateSql()

        sql.execute(
            "update table_z ...",
            [...]
        )

        ...

        this.discard()  // remove the object from the hibernate session
        return true
    }

Кроме того, вы можете добавить это в ваш Config.groovy, чтобы потребовать явного сохранения объектов:

hibernate.flush.mode="manual"
0 голосов
/ 12 октября 2010

Если вы используете read () вместо get (), то объект не будет автоматически сохранять изменения. Вы все еще можете вызвать save () явно, но стандартное поведение, при котором перехватчик OpenSessionInView сбрасывает все несохраненные грязные экземпляры, пропускает экземпляры, загруженные с помощью read ().

...