Cayenne: обновление базы данных вручную созданными экземплярами классов, сгенерированными cayenne.

Я пытаюсь использовать cayenne для взаимодействия с базой данных PostgreSQL. До сих пор все работало так, как ожидалось, но теперь я столкнулся с проблемой, которую не совсем понимаю (я новичок в кайенне).

Скажем, у меня есть таблица «книги» с обычными полями (книга_id, название, редактор, цена), «таблица» авторов (автор_ид, автор_имя) и таблица ссылок «книги_авторы» (книга_ид, автор_ид).

Все классы, связанные с процессом добавления или редактирования книги, совместно используют один DataContext.

У меня есть форма struts2 (я использую шаблоны скорости), которая позволяет вам добавить книгу и, используя ajax, несколько связанных с ней авторов. Я реагирую на определенное событие, чтобы запустить запрос ajax, который вызывает действие struts2, которое проверяет, существует ли автор, а затем добавляет объект Books_Authors (класс, сгенерированный cayenne) в сеанс struts2 (действие реализует SessionAware).

Форма выглядит следующим образом:

<form action="AddOrEditBook.do">
    <input type="hidden" name="book.book_id" value="$!book.book_id" />

    <input type="text" name="book.title" value="$!book.title" />

    <input type="text" name="book.editor" value="$!book.editor" />

    <input type="number" name="book.price" value="$!book.price" />

    <input type="text" name="author" /> <input type="button" name="addAuthor" value="Add" />

    <ul>
        <li id="author_2">Author 2 <input type="button" name="removeAuthor" value="Remove" /></li>
        <li id="author_16">Author 16 <input type="button" name="removeAuthor" value="Remove" /> </li>
    </ul>

    <input type="submit" />
</form>

Как только я отправляю форму в AddOrEditBook.do, у которого есть сеттер и геттер для книги, struts2 создает объект книги и заполняет его значениями формы. Это мило.

Вот что меня смущает:

Когда я обновляю книгу, я не нашел способа использовать объект, созданный struts, для обновления базы данных. Чего я хочу добиться, так это каким-то образом указать cayenne использовать объект, созданный struts, для обновления соответствующего объекта в базе данных.

Я много напутал с такими вещами, как object_id, PersistenceState и т.д.:

Expression exp_book = ExpressionFactory.matchExp(Book.BOOK_ID_PROPERTY, book.getBook_id());
Book bookFromDb = RetrieveHelper.retrieveScalarByExpression(ctxt, new Book(), exp_book);

book.setObjectContext(ctxt);
book.setObjectId(bookFromDb.getObjectId());
ctxt.getObjectStore().registerNode(book.getObjectId(), book);
book.setPersistenceState(PersistenceState.MODIFIED);

Какова правильная стратегия при использовании cayenne для обновления объектов БД? Возможно ли это сделать только с помощью таких вещей, как bookFromDb.setTitle(book.getTitle()); ?

Спасибо!


person ixM    schedule 08.06.2012    source источник


Ответы (1)


struts2 создает объект книги и заполняет его значениями формы. Это мило.

Я не эксперт Struts2, но из того, что я читаю в документах о жизненном цикле объекта формы, такой объект создается Struts2 путем вызова конструктора по умолчанию. Если нет способа переопределить это поведение, заменив его какой-либо фабрикой, которая даст вам объект Cayenne из правильного DataContext, то то, что вы делаете здесь, является правильным — вы отделяете объект значения, прикрепленный к форме (и класс действий) из постоянного объекта.

С другими фреймворками, такими как Tapestry и т. д., вы можете напрямую привязать форму к постоянному объекту Cayenne. Может быть, вы можете расширить Struts2 аналогичным образом?

Все классы, связанные с процессом добавления или редактирования книги, совместно используют один DataContext.

Бессвязный совет. У вас должен быть как минимум отдельный DataContext для каждого пользователя (например, поместите его в HttpSession). Или, если вы не сохраняете незафиксированное состояние между запросами - может быть, даже один DataContext на запрос. Другими словами, не делитесь DataContext, если они не доступны только для чтения. В противном случае ваше приложение не является потокобезопасным.

person andrus_a    schedule 11.06.2012
comment
Спасибо за подробный ответ, особенно за вторую часть. Я не знал, как struts2 обрабатывает действия и особенно члены связанных с ним классов. Насколько я понимаю, DataContext, который я храню, на самом деле полностью глобальный, поэтому у каждого пользователя, подключенного к приложению, будет один и тот же, что, конечно же, не то, что я планировал! - person ixM; 11.06.2012