JPA比预期更多的实例

时间:2014-05-23 15:55:41

标签: java jpa

我有一个名为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
  • 存在15个实例
  • 对于数据库中的每一行,似乎总是存在三个实例。
  • 比较所有字段,它们似乎相等。即使字符串的id似乎也是相同的。我不应该getHash()返回相同内容而equals()应该返回true吗?

最后一点让我震惊,因为我没有在我的应用程序中任何地方实现它们!有人知道这发生的时间吗?

如果JPA使用缓存(是吗?),它应该使用@Id列查看以前创建的项目。即使我做了多个createQuery,他们也应该引用相同的项目。或者我错了吗?

对我来说这一切都很奇怪,我也不知道如何调试它。

我希望有人能在黑暗中带来一些亮光。

编辑:我所能说的是,只要我第一次使用相应的JPA请求,就会存在这15个实例。在构造函数中放置调试器陷阱,我可以确认所有实例都是一个接一个地创建的。

Edit2:为了实现测试的乐趣,我只是尝试重新实现hashCode()(简称return this.id;)并覆盖equals()return this.id == other.id;

15个实例仍在那里。因为我只是在阅读,所以我现在不关心它,因为我现在可以将所有这三个实例视为一个相同的项目。但它不是基本问题的解决方案。我怀疑这可能会在其他地方发生 - 没有经过测试。

1 个答案:

答案 0 :(得分:1)

如果我理解的话,你在数据库中有5个元组,地图中有5个不同的实例(假设名称是唯一的?)和JPA加载的15个不同的实例,它们等于3个组... < / p>

我想这是Cache Level的问题。

如果加载的实例存储在持久性上下文缓存 - 级别2(即EntityManager)中 - 而不是持久性单元缓存 - 级别1,则EclipseLink可能会为同一元组创建不同的相等实例(即EntityManagerFactory)。您可能会为每个读取操作使用不同的EntityManager。在这种情况下,EclipseLink无法找到以前缓存的实体。

这取决于您的应用程序配置。问题还可能是内存不足和弱引用缓存引起的。 EclipseLink cache documentations页面提供了进一步的说明。