2014-05-23 26 views
4

我有一个名为NodeType的类,使用JPA通过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 

Somewhen后,我不知道究竟哪里发生这种情况,多个实例为每个项目突然存在(每件3个实例当前)

示例:在应用程序中,我有一个实例节点类型与值

1 NTYPE_HUP 0   NodeHangup 

Eclipse调试器告诉我说:

  • 在我的地图,T这里实际上具有高于
  • map.get回报null如所提到的情况相同的值此实例
  • 15个实例的类NodeType
  • 数据库中的各行存在一个项目,总是三个实例似乎存在。
  • 比较所有的字段,它们似乎是平等的。即使是字符串id似乎是相同的。不应该getHash()返回相同和equals()应该返回true然后呢?

最后一点让我震惊,因为我并没有在我的应用程序中的任何位置实例化它们!有人知道这是什么时候发生的吗?

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

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

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

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

EDIT2:的乐趣和测试的缘故,我只是试图去解决它周围重新实现hashCode()(简单return this.id;)和压倒一切的equals()return this.id == other.id;

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

+0

答案可能不是,但只是为了确保。你在合并实体吗?合并返回新对象。你JPA的实现是什么? – skegg99

+0

不,我不知道。正如我所说的:我启动应用程序,做一些不相关的东西,然后执行某种findAll-query和tadaa,我拥有所有的实例。没有合并,在这个时候不会调用'persist()'。在代码中我没有添加任何东西到这个表中。 – Atmocreations

+0

啊,我的实现是EclipseLink。 – Atmocreations

回答

1

如果我理解的很好,那么在数据库中有5个元组,在映射中有5个不同的实例(假设名称是唯一的?)和JPA加载的15个不同的实例,这些实例与3组相等。

我想这是一个问题Cache Level

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

这取决于您的应用程序配置。这个问题也可能是由于内存不足和参考缓存较弱造成的。有关详细说明,请参阅EclipseLink cache documentations页面。