ORM — ошибка связанной таблицы

Я работаю над приложением для блога, используя ColdBox 3.5 и ColdFusion 10 ORM, и случайно получаю следующее сообщение об ошибке:

Тип ошибки: Приложение: [Н/Д]

Сообщения об ошибках: исключение в режиме гибернации. Либо обновленная/удаленная строка не существует, либо сеанс содержит устаревшие данные.

Основная причина: org.hibernate.StaleObjectStateException: строка была обновлена ​​или удалена другой транзакцией (или сопоставление несохраненных значений было неверным): [Entry#297e1bfa369cf17501369d26ffae00a4]

/model/entry/Entry.cfc:

component
    persistent="true"
    table="Entry"
    output="false"
{
    // primary key
    property name="entryID" fieldtype="id" ormtype="string" type="string" length="32" generator="uuid";

    // properties
    property name="title" fieldtype="column" ormtype="string" type="string" length="100" notnull="true";
    property name="alias" fieldtype="column" ormtype="string" type="string" length="100" notnull="true";
    property name="body" fieldtype="column" ormtype="string" type="string" sqltype="nvarchar(max)" notnull="true";
    property name="allowComments" fieldtype="column" ormtype="boolean" type="boolean" sqltype="bit" dbdefault="1" default="true" notnull="true";
    property name="released" fieldtype="column" ormtype="boolean" type="boolean" sqltype="bit" dbdefault="1" default="true" notnull="true";
    property name="releasedDate" fieldtype="column" ormtype="timestamp" type="date";
    property name="addDate" fieldtype="timestamp" ormtype="timestamp" type="date";

    // relations
    property name="categories" fieldtype="many-to-many" cfc="model.category.Category" linktable="EntryCategory" fkcolumn="entryID" inversejoincolumn="categoryID" singularname="category" cascade="all" lazy="true";
    property name="comments" fieldtype="one-to-many" cfc="model.entryComment.EntryComment" fkcolumn="entryID" singularname="comment" cascade="all-delete-orphan";
    property name="user" fieldtype="many-to-one" cfc="model.user.User" fkcolumn="userID" notnull="true" cascade="save-update";
    property name="views" fieldtype="one-to-many" cfc="model.entryView.EntryView" fkcolumn="entryID" singularname="view" cascade="all-delete-orphan";

    // validation
    this.constraints = {
        "title" = {"required" = true},
        "body" = {"required" = true},
        "allowComments" = {"required" = true, type="boolean"},
        "released" = {"required" = true, type="boolean"},
        "categories" = {size=1},
        "user" = {type="component"}
    };
}

/model/category/Category.cfc:

component
    persistent="true"
    table="Category"
    schema="system"
    output="false"
{
    // primary key
    property name="categoryID" fieldtype="id" ormtype="string" type="string" length="32" generator="uuid";

    // properties
    property name="name" fieldtype="column" ormtype="string" type="string" length="50" notnull="true";
    property name="alias" fieldtype="column" ormtype="string" type="string" length="50" notnull="true";
    property name="description" fieldtype="column" ormtype="string" type="string" default="" length="200";
    property name="addDate" fieldtype="timestamp" ormtype="timestamp" type="date";
    property name="active" fieldtype="column" ormtype="boolean" type="boolean" sqltype="bit" dbdefault="1" default="true" notnull="true";

    // relations
    property name="entries" fieldtype="many-to-many" cfc="model.entry.Entry" linktable="EntryCategory" fkcolumn="categoryID" inversejoincolumn="entryID" lazy="true" cascade="all" singularname="entry" inverse="true";

    // validation
    this.constraints = {
        "name" = {"required" = true},
        "active" = {"required" = true, type="boolean"}
    };
}

Вот код, который я запускаю:

<cfscript>
    entry = entityNew("Entry", {
        "title" = "test",
        "body" = "test",
        "alias" = "test",
        "allowComments" = 0,
        "released" = 0,
        "user" = entityLoadByPK("User", "297e1bfa3697d377013697f53ca10084")
    });

    // works 1 out of 5 times
    entry.setCategories([entityLoadByPK("Category", "297e1bfa36986e69013698c3e54f000d")]);

    // works every time
    //entry.setCategories(entityLoad("Category", "297e1bfa36986e69013698c3e54f000d"));
    //entry.setCategories(entityLoad("Category"));

    entitySave(entry);
    ormFlush();
</cfscript>

Обратите внимание на разделы, помеченные как «работает 1 из 5 раз» и «работает каждый раз». Я не понимаю, что я делаю неправильно. У меня есть другие объекты, подобные этим, где они используют связанную таблицу, и я получаю аналогичные сообщения об ошибках. Я просмотрел журнал SQL. Ошибка появляется, когда он готов к вставке в таблицу EntryCategory. Любые идеи?


person Peruz Carlsen    schedule 10.04.2012    source источник
comment
Будет ли entry.addCategory(entityLoadByPK("Category", "297e1bfa36986e69013698c3e54f000d")) работать лучше?   -  person Henry    schedule 10.04.2012
comment
Не совсем. Страница обслуживания, которую я использую, настроена так, чтобы пользователь мог выбирать несколько категорий. Итак, что мне нравится делать, так это преобразовывать значения ID в массив сущностей, а затем делать entry.setCategories(my_category_array)   -  person Peruz Carlsen    schedule 10.04.2012
comment
Если это так, используйте HQL и используйте идентификатор where в (?). Это работает очень хорошо. Если у объекта уже есть массив, сначала используйте ArrayClear().   -  person Henry    schedule 10.04.2012
comment
Я сделал то, что вы предложили, и это сработало отлично :) Спасибо. Можете ли вы назвать какие-либо причины, по которым то, что я сделал, не сработало? Это просто не имеет смысла.   -  person Peruz Carlsen    schedule 10.04.2012
comment
Я не уверен, вы можете отправить отчет об ошибке. :) bugbase.adobe.com   -  person Henry    schedule 10.04.2012
comment
Вы говорите, что используете CF10, но пометили как CF9. Что он?   -  person ale    schedule 10.04.2012


Ответы (1)


Используйте HQL и используйте ID в (?). Это работает очень хорошо.

Если у объекта уже есть массив, сначала используйте ArrayClear().

ОБНОВИТЬ:

categories = ormExecuteQuery("from Category where Id IN (:Ids)",
                             {Ids=listToArray(FORM.categoryIDs)});
entry.setCategories(categories);
person Henry    schedule 10.04.2012
comment
Не могли бы вы добавить туда небольшой (псевдо) код. Использование HQL не очень полезно для тех, кто только учится использовать ORM. - person ale; 10.04.2012