我们从一个小表'ACCESS_STATUS'中获取数据,如下所示。
ID NAME 1外部 2内部
当我们使用以下JPA代码时:在特定情况下,当两个用户同时访问此表时,第一行的Name列将被提取为NULL。此字段进一步使用,因此抛出空指针异常,应用程序停止工作,必须重新启动。
JpaEntityManager jpaEm = JpaHelper.getEntityManager(em);
ReadAllQuery query=new ReadAllQuery(AccessStatus.class);
Collection accessStatus = (Collection)jpaEm.getActiveSession().executeQuery(query)
如果我使用如下的原生查询,则不存在此问题:
try {
preparedStatement=connection.prepareStatement(sb.toString());
resultSet=preparedStatement.executeQuery();
while (resultSet.next()) {
id = resultSet.getString(1);
name = resultSet.getString(2);
accessStatus.add(new AccessStatus(id,name));
}
}
这是JPA / Java EE中的错误吗?什么是此问题的永久性解决方案?
答案 0 :(得分:1)
这不是严格的JPA,因为您正在访问EclipseLink会话以执行本机ReadAllQuery。严格的JPA将是
Collection accessStatus = em.createQuery("Select status from AccessStatus status").getResultList();
但它可能会给你相同的结果。问题可能不是JPA / EclipseLink / ORM错误,而是您的应用程序如何使用这些工具。首先,返回的实体将成为一个管理实体,并反映您在会话/上下文中所做的任何更改 - 甚至是未经修改的实体。因此,请检查您是否以某种方式合并或持久化实体或以其他方式填充具有空名称的实体。常见错误是应用程序创建新实体,并在建立与现有实体的关系时,而不是使用find或getReference调用获取它,只需创建一个新的空实例。这设置了外键,但是你得到了你输入的内容,除非刷新该对象,否则将丢失数据。
您可以通过在查询返回的AccessStatus上调用em.refresh()来验证是否发生了这种情况。如果随后填充了名称,则应该使用空值来跟踪它进入上下文的方式。