我有一个简单的Play应用程序进行测试。我有2个控制器,一个是“ListController”,它显示条目列表。每个条目都有一个“编辑”链接,该链接转到“EditController”。 “EditController”将html表单与该条目的现有数据一起显示,并且Submit按钮将该数据发布到“EditController”中的另一个方法,该方法将数据保存到db并在表单中重新显示新修改的数据。所有这些都可以。但是,一旦我修改了一个条目(在编辑页面中正确显示了该条目),当我返回列表时,该条目仍然具有旧值,并且对其进行编辑仍会显示旧值。在测试和开发环境中都会发生这种情况。
这是我的设置:
@OnApplicationStart
初始化data.yml文件中的数据%test.db = fs
%test.jpa.ddl =创建
db = postgres:// postgres:postgre @ localhost:5432 / play
列出洗衣清单= LaundryList.findAll();
-EditController
LaundryList updatedLaundryList = LaundryList.em().merge(laundryList);
我已经添加了日志输出,并且肯定地,在EditController中调用
merge
方法之后,即使我添加了从数据库中检索更新的实体的代码,它也会返回具有正确更新值的Bean,例如我如何插入它们但是,即使在此之后,在我重新输入(或单击链接)ListCOntroller的测试(播放测试)或运行(播放运行)环境中,它仍然显示(据说)已修改的条目,其值与更新之前相同发生在EditController中。如果我再次单击以对其进行编辑,则该表单将向我显示该条目的从未修改过的初始数据。
我的问题是,我应该怎么做才能将数据持久保存到数据库中?
最佳答案
我找到了解决方案,但这非常令人失望。
简而言之,我所做的就是替换此行:
LaundryList.em()。merge(laundryList);
有了这个:
LaundryList updateLaundryList = LaundryList.em().merge(laundryList);
updateLaundryList.save();
长答案是:播放更改了JPA的实际工作方式。在上述情况下,我正在事务中(日志清楚地表明了这一事实,并且如果我尝试启动事务,则会引发异常,告诉我实际上我已经在运行事务了)。但是,即使如此,执行
em().merge
实际上也不会对数据库进行任何插入/更新,如日志中所示。是的,在他们网站上的某个时刻,他们确实说了一些话:“我们不喜欢在进行事务处理时JPA如何自动同步数据,因此您不需要调用持久/合并,但是您确实实际上需要调用刷新来撤消您的更改,我们不喜欢这样做,所以我们撤消了它:现在您必须显式保存,否则什么也不会更新。”
他们还说(在这里我找到了实际的报价):
“在连续的请求期间,使用对象ID从数据库中检索对象,对其进行更新,然后再次保存。”
就是这样。没有代码示例就没有。由于他们改变了一个比Play更广为人知的框架(即JPA)的行为,因此,他们应该更清楚地指定它,或者至少更改类名,进行包装,说他们做了自己的PlayPersistenceManager或其他东西。 。
不,我个人认为他们的方法没有更好的选择。总体而言,您保留/更新某些内容的可能性要比撤消某些更改的可能性更大,因此,如果保留/更新自动发生(没有样板代码)并且您需要明确执行撤消操作,则更好。