我有一个名为“JobStatus”的游戏模型,它只有一个属性,一个带有JobState的枚举,(Running / notRunning)。
该类扩展模型并实现为单例。您可以调用它的getInstance()方法来获取基础表中的唯一记录。
我有一个每月运行的工作,在工作中我将在不同时间来回切换JobStatus对象的状态并调用.save()。
我注意到它实际上并没有保存。
当作业开始时,它的第一行代码是
JobStatus thisJobStatus = jobStatus.getInstance();
...// exit if already running
thisJobStatus.JobState = JobState.Running;
thisJobStatus.save()
然后当作业完成时,它会将状态更改回NotRunning并再次保存。
问题在于,当我查看MySql数据库时,实际记录值永远不会改变。
这会导致灾难性故障,因为当其他节点尝试运行作业时,他们会检查状态,因为他们将其视为NotRunning,所以他们都会尝试运行该作业。
因此,我管理作业状态的聪明方案失败了,因为实际值没有被提交给数据库。
当我在模特上调用.save()时,如何强制Play立即写入数据库?
由于 约什
答案 0 :(得分:3)
尝试将此添加到JobStatus并在保存后调用它。
public static void commit(){
JobStatus.em().getTransaction().commit();
JobStatus.em().getTransaction().begin();
JobStatus.em().flush();
JobStatus.em().clear();
}
答案 1 :(得分:0)
我想你想把你的工作标记为“正在运行”,就像工作开始时的第一件事一样?在这种情况下,您还不应该有任何其他正在进行的数据库语句......
要立即在数据库中提交更改(而不是在作业结束后),请在thisJobStatus.save();
方法调用之后添加以下命令:
JPA.em().flush();
JPA.em().getTransaction().commit();
此外,由于您使用的是MySQL,因此您可能希望在使用SELECT ... FOR UPDATE
子句后立即锁定该行。 (有关详细信息,请参阅MySQL Reference Manual。)当然,您不希望在getInstance()
方法中使用此方法,否则每次提取操作都会锁定记录。