Play框架:合并操作仅适用于触发它的Controller

时间:2011-11-15 20:00:21

标签: java model merge playframework

我有一个简单的Play应用程序用于测试。我有2个控制器,一个是显示条目列表的“ListController”。每个条目都有一个“编辑”链接,转到“EditController”。 “EditController”将html表单与条目的现有数据一起显示,并且“提交”按钮将该数据发布到“EditController”中的另一个方法,该方法将数据保存到db并重新显示表单中新修改的数据。这一切都运转正常。但是,当我在返回列表时修改一个条目(在编辑页面中正确地重新显示)时,该条目仍然具有旧值,并且编辑它仍然使用旧值显示它。这在测试和开发环境中都会发生。

这是我的设置:

  • 通过@OnApplicationStart带注释的BootStrap类
  • 从data.yml文件初始化数据
  • 配置的测试环境:

    %test.db的= FS

    %test.jpa.ddl =创建

  • dev环境配置为:

分贝= postgres的:// postgres的:postgre @本地:5432 /播放

  • ListController:

    列出LaundryLists = LaundryList.findAll();

-EditController

LaundryList updatedLaundryList = LaundryList.em().merge(laundryList);

我已经添加了日志输出,当然,在调用EditController中的merge方法之后,即使我添加代码以从数据库中检索更新的实体,它也会返回一个具有正确更新值的bean,例如我如何插入它们

然而,即使在此之后,在我重新键入(或单击链接)ListCOntroller时,在测试(播放测试)或运行(播放运行)环境中,它仍然显示具有其具有的值的(据称)修改的条目在EditController中发生更新之前。如果我再次点击进行编辑,表单会向我显示该条目的初始未修改数据。

我的问题是,我应该怎么做才能将数据保存到数据库?

1 个答案:

答案 0 :(得分:6)

我找到了解决方案,但这非常令人失望。

简而言之,我所做的就是替换这一行:

LaundryList.em()合并(laundryList);

用这个:

LaundryList updateLaundryList = LaundryList.em().merge(laundryList);
updateLaundryList.save();

答案很长:Play改变了JPA实际工作的方式。在上面的例子中,我处于一个事务中(日志清楚地显示了这一事实,如果我尝试启动事务,则会引发一个异常,告诉我我实际上已经处于已经运行的事务中)。但是,即便如此,执行em().merge实际上并没有对数据库执行任何插入/更新,如日志中所示。

是的,在他们网站的某个时刻,他们会说“我们不喜欢JPA在您进行交易时自动同步数据,因此您不需要调用persist / merge,但你确实需要调用刷新你想要撤消你的更改,我们不喜欢这样,所以我们改掉了它:现在你必须明确保存,否则什么都不会更新“。

他们也说(在这里我找到了实际的报价):

“在连续请求期间,使用对象ID从数据库中检索对象,更新它,然后再次保存。”

但就是这样。没有代码示例也没有。因为他们改变了比Play更为人所知的框架(即JPA)的行为,所以他们应该更清楚地指明这一点,或者至少改变类名,制作包装器,说他们自己制作PlayPersistenceManager或者其他东西

不,不,我个人不认为他们的方式更好。总的来说,你很可能坚持/更新某些东西而不是撤消一些变化,所以如果持久化/更新自动发生(没有样板代码)并且你需要明确地进行撤销,那就更好了。 p>