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

Java Cayenne:使用手动创建的Cayenne生成的类实例更新数据库,java,struts2,apache-cayenne,Java,Struts2,Apache Cayenne,我正在尝试使用cayenne与PostgreSQL数据库交互。到目前为止,一切都按预期进行,但我现在遇到了一个我不太理解的问题(我是cayenne的新手) 假设我有一个带有常用字段(图书id、标题、编辑、价格)的表“books”,一个“表”authors(作者id、作者姓名)和一个链接表“books作者”(图书id、作者id) 与添加或编辑书籍的过程相关联的所有类都共享一个DataContext 我有一个struts2(我使用velocity模板)表单,它允许您添加一本书,并使用ajax添加与之

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

假设我有一个带有常用字段(图书id、标题、编辑、价格)的表“books”,一个“表”authors(作者id、作者姓名)和一个链接表“books作者”(图书id、作者id)

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

我有一个struts2(我使用velocity模板)表单,它允许您添加一本书,并使用ajax添加与之相关联的多个作者。我对某个事件做出反应,触发一个ajax请求,该请求调用一个struts2操作,该操作验证作者是否存在,然后向struts2会话添加一个Books_Authors对象(由cayenne生成的类)(该操作实现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>
使用cayenne更新db实体时,正确的策略是什么?只有通过制作bookFromDb.setTitle(book.getTitle());,才能做到这一点吗

谢谢

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

我不是Struts2专家,但从我在文档中读到的关于表单对象生命周期的内容来看,这样的对象是由Struts2通过调用默认构造函数创建的。除非有一种方法可以覆盖此行为,将其替换为某个工厂,该工厂将从正确的DataContext中为您提供一个Cayenne对象,否则您在这里所做的是正确的—将附加到表单(和action类)的值对象与持久对象分离

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

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


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

感谢您的详细回答,尤其是第二部分。我不知道struts2如何处理动作,尤其是与之相关的类的成员。正如我现在所理解的,我存储的DataContext实际上是完全全局的,因此连接到应用程序的每个用户都将拥有相同的DataContext,这当然不是我想要的!
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);