Grails не может сохранить объект, который уже существует в сеансе?

Возможный дубликат:
Spring + Hibernate: другой объект с тем же значением идентификатора уже был связан с сеансом

У меня есть три домена, похожие на пример ниже:

class Computer {
    static hasMany = [progStartTimes:ProgStartTime]
    static belongsTo = User

    static constraints = {
        name()
        operatingSystem()
        processor()
    }

    User owner
    OperatingSystem os
    Processor processor
}

class OperatingSystem {
    static hasMany = [computers:Computer]

    static constraints = {
        name(blank:false,unique:'versionType',maxSize:80)
        versionType()
    }

    static mapping = {
        versionType type:VersionTypeMapping
    }

    String name
    VersionType versionType
}

class ProgStartTime implements Serializable {
    static constraints = {
        computer()
        program()
        duration()
    }

    static mapping = {
        id composite:['computer','program']
        duration type:DurationMapping
    }

    Computer computer
    Program program
    Duration duration
}

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

org.springframework.orm.hibernate3.HibernateSystemException: a different object
with the same identifier value was already associated with the session:
[diag.ProgStartTime#diag.ProgStartTime : null]; nested exception is
org.hibernate.NonUniqueObjectException: a different object with the same
identifier value was already associated with the session:
[diag.ProgStartTime#diag.ProgStartTime : null]

Вот раздел кода контроллера, который сохраняет объекты. Кто-нибудь знает, что происходит?

ownerInstance.withTransaction { status ->
    try {
        if (operatingSystem.id == null) {
            operatingSystem.save()
        }

        if (processor.id == null) {
            processor.save()
        }

        startTimes.each {
            if (it.id == null) {
                it.save()
        }
    } catch (Exception e) {
        ownerInstance.errors.reject("Failed to save the necessary objects: " + e)
        status.setRollbackOnly()
    }
}

person Jesse    schedule 09.03.2012    source источник


Ответы (1)


Сопоставление вашего идентификатора для ProgStartTime — это то, что я нечасто использовал в Grails, но после просмотра мне кажется, что, создавая этот составной идентификатор, вы гарантируете уникальность ProgStartTime. что никакие двое не будут делить и Компьютер, и Программу.

Если вы нарушаете это ограничение, я ожидаю увидеть ошибку, подобную той, которую видите вы. Проверьте, какие данные вы вводите, по сравнению с тем, что находится в таблице данных ProgStartTime, чтобы увидеть, не в этом ли проблема. Если это что-то другое, я сделаю все возможное, чтобы помочь дальше :)

Из любопытства, какую версию Grails вы используете?

person Will Buck    schedule 09.03.2012
comment
Это на Grails 2.0.1. Сейчас я проверяю данные. - person Jesse; 13.03.2012
comment
Наверное, надо было просто подождать. Во всяком случае, я просмотрел данные и убедился, что нет дубликатов или конфликтов. Насколько я могу судить, этого не должно происходить с точки зрения данных. Это также происходит только с определенными данными, а не случайными, но я не могу понять, что в этих данных такого особенного. - person Jesse; 13.03.2012
comment
Хм, интересно. Можете ли вы привести пример некоторых данных в таблицах и пример ввода данных, который вызывает эту ошибку? - person Will Buck; 13.03.2012
comment
Не осмысленно. :-/ В фактическом коде больше полей и тонна данных, которые я не могу публиковать здесь как для краткости, так и для целей занятости. Есть ли способ позволить Grails более подробно регистрировать или детализировать причину исключения? Редактировать: Если вам все равно нужны примеры данных, я могу их опубликовать. Какой домен (ы) вы бы предпочли, или вы хотите понемногу от каждого? - person Jesse; 13.03.2012
comment
О, это, вероятно, будет непростым упражнением, не так ли :/ Попробуйте проверить эти ссылки и посмотрите, помогут ли они! stackoverflow.com/questions/4194350/ grails.1312388.n4.nabble.com/ - person Will Buck; 13.03.2012
comment
На самом деле я уже видел эти ссылки, но они относятся к использованию метода merge() вместо save(). Я согласен с этим, но я хотел бы знать, как объекты, которые я создаю, выпадают из сеанса Hibernate, поскольку я делаю все это с контроллера. - person Jesse; 13.03.2012
comment
На самом деле, не похоже, что merge() тоже работает. Когда я использую функцию merge(), некоторые объекты ProgStartTime вызывают исключение NullPointerException. Я не уверен, что это значит, тем более что объект действительно существует. - person Jesse; 13.03.2012
comment
Боюсь, что на данный момент у меня нет идей, Джесси :/ Если я придумаю что-нибудь еще, я дам тебе знать! - person Will Buck; 13.03.2012