Cayenne:使用由cayenne生成的手动创建的类实例更新数据库

时间:2012-06-08 09:32:02

标签: java struts2 apache-cayenne

我正在尝试使用cayenne与PostgreSQL数据库进行交互。到目前为止,一切都按预期工作,但我现在遇到了一个我不太了解的问题(我是cayenne的新手)。

假设我有一个表“书籍”,包含常用字段(book_id,title,editor,price),“table”作者(author_id,author_name)和链接表“books_authors”(book_id,author_id)。

与添加或编辑图书的过程相关联的所有类共享一个DataContext。

我有一个struts2(我使用速度模板)表单,可以让你添加一本书,并使用ajax,与之关联的多个作者。我对某个事件做出反应来触发一个调用struts2动作的ajax请求,该动作验证作者是否存在,然后将一个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>

一旦我将表单提交给具有setter和getter for book的AddOrEditBook.do,struts2就会创建book对象并使用表单的值填充它。那太好了。

这让我困扰的是:

当我更新一本书时,我没有找到一种方法来使用struts创建的对象来更新数据库。我想要实现的是以某种方式指示cayenne使用struts创建的对象来更新db中的相应实体。

我对诸如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())之类的东西来做到这一点; ?

谢谢!

1 个答案:

答案 0 :(得分:1)

  

struts2创建book对象并使用表单的值填充它。那很好。

我不是Struts2专家,但是从我在关于表单对象生命周期的文档中读到的内容,这个对象是由Struts2通过调用默认构造函数创建的。除非有一种方法可以覆盖这种行为,将其替换为一个可以从正确的DataContext给你一个Cayenne对象的工厂,你在这里做的是正确的 - 你要分离附加到表单的值对象(和动作类)来自持久对象。

使用Tapestry等其他框架,您可以直接将表单绑定到Cayenne持久对象。也许你可以以类似的方式扩展Struts2?

  

与添加或编辑图书的过程相关联的所有类共享一个DataContext。

一条不相关的建议。您必须至少为每个用户提供单独的DataContext(例如,将其放在HttpSession中)。或者,如果您不在请求之间保持未提交状态 - 甚至可能每个请求一个DataContext。换句话说 - 除非它们是只读的,否则不要共享DataContexts。否则你的应用程序不是线程安全的。