我有一个名为NodeType
的类,由SQL Server数据库使用JPA进行备份。
没有什么特别的,没有关系,只有一些领域。还有更多,但为简化起见,我省略了它们:
@Entity
@Table(name="node_type")
@NamedQuery(name="NodeType.findAll", query="SELECT n FROM NodeType n")
public class NodeType implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
public NodeType() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
启动我的应用程序时,我会阅读它们并将它们全部放入HashMap
,将属性name
作为关键,以便以后更轻松地找到它。
在数据库中,目前有五个项目。
id name maxNoExits mandatoryExits defaultExits
== ========= ========== ============== ============
1 NTYPE_HUP 0 NodeHangup
2 NTYPE_ANN 1 NodeAnnounce
3 NTYPE_SLP 1 NodeWait
4 NTYPE_XFR 0 NodeTransfer
5 NTYPE_TBR 32 NodeTimebased
稍后,我不知道究竟发生了什么,每个项目的多个实例突然存在(目前每个项目3个实例)
示例:在应用程序中,我有一个NodeType实例,其值为
1 NTYPE_HUP 0 NodeHangup
eclipse调试器告诉我:
map.get
为此实例返回null
NodeType
id
似乎也是相同的。我不应该getHash()
返回相同内容而equals()
应该返回true
吗?最后一点让我震惊,因为我没有在我的应用程序中任何地方实现它们!有人知道这发生的时间吗?
如果JPA使用缓存(是吗?),它应该使用@Id
列查看以前创建的项目。即使我做了多个createQuery
,他们也应该引用相同的项目。或者我错了吗?
对我来说这一切都很奇怪,我也不知道如何调试它。
我希望有人能在黑暗中带来一些亮光。
编辑:我所能说的是,只要我第一次使用相应的JPA请求,就会存在这15个实例。在构造函数中放置调试器陷阱,我可以确认所有实例都是一个接一个地创建的。
Edit2:为了实现测试的乐趣,我只是尝试重新实现hashCode()
(简称return this.id;
)并覆盖equals()
( return this.id == other.id;
)
15个实例仍在那里。因为我只是在阅读,所以我现在不关心它,因为我现在可以将所有这三个实例视为一个相同的项目。但它不是基本问题的解决方案。我怀疑这可能会在其他地方发生 - 没有经过测试。
答案 0 :(得分:1)
如果我理解的话,你在数据库中有5个元组,地图中有5个不同的实例(假设名称是唯一的?)和JPA加载的15个不同的实例,它们等于3个组... < / p>
我想这是Cache Level的问题。
如果加载的实例存储在持久性上下文缓存 - 级别2(即EntityManager)中 - 而不是持久性单元缓存 - 级别1,则EclipseLink可能会为同一元组创建不同的相等实例(即EntityManagerFactory)。您可能会为每个读取操作使用不同的EntityManager。在这种情况下,EclipseLink无法找到以前缓存的实体。
这取决于您的应用程序配置。问题还可能是内存不足和弱引用缓存引起的。 EclipseLink cache documentations页面提供了进一步的说明。