我遇到了一个我不知道如何解决的问题(和往常一样,这可能是我身边的一个愚蠢的错误)。我正在使用Embedded Derby和JPA(EclipseLink)编写Java SE Swing应用程序。没有多用户,虽然我可以打开几个tabbedpanes来执行不同的操作。但是,在这个问题中,我使用单个窗格来重现问题。
在该测试面板中,每当我将其添加为选项卡式窗格时,我都会运行以下代码:
public void onTabPanelAdded() {
if (entityManager == null) {
// emf is a static property in the Main class
// so I just create one EntityManagerFactory,
// but one EntityManager for each JPanel
entityManager = emf.createEntityManager();
}
selectedL10n = entityManager.find(L10n.class, 1);
l10nCodeField.setText(selectedL10n.getCode());
descripField.setText(selectedL10n.getName());
l10nCodeField.requestFocusInWindow();
}
每当我关闭选项卡式窗格(隐藏JPanel)时,我都会运行以下代码:
public void onTabPanelRemoved() {
if (entityManager.getTransaction().isActive()) {
entityManager.flush();
entityManager.getTransaction().commit();
}
entityManager.close();
entityManager = null;
}
虽然在关闭/隐藏JPanel之前发生了错误(只是为了让你不再认为它与不释放EntityManager有关)。
现在,正如您在第一个代码块中看到的那样,测试面板从数据库中检索持久化实体并填充面板中的TextFields。在对数据进行简单更改并单击我输入的“保存”按钮后,运行以下代码:
private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {
entityManager.getTransaction().begin();
selectedL10n = entityManager.merge(selectedL10n);
selectedL10n.setCode(l10nCodeField.getText());
selectedL10n.setName(descripField.getText());
try {
entityManager.getTransaction().commit();
} catch (Exception ex) {
Logger.getLogger(L10nGUIManager.class.getName()).log(
Level.SEVERE, null, ex);
}
}
如您所见,我打开事务,合并实体以确保它被管理(我通过使用entityManager.contains(selectedL10n)对此进行了双重检查),应用更改并提交。然而,尽管没有应用程序的其他部分且没有其他实例/用户正在使用它,但我得到了一个OptimisticLockException。我根本就不明白。
该实体具有带注释的版本字段:
@Entity
public class L10n implements Serializable, Comparable<L10n> {
@Version
private int entityVersion;
...
与他相应的getter / setter。我完全迷失了原因。
TIA