【问题标题】:JPA Map w/ Entity Key and Entity Value带有实体键和实体值的 JPA 映射
【发布时间】:2012-02-02 17:27:57
【问题描述】:

关键实体:

@Entity public class KeyEntity
{
    @Id @GeneratedValue(strategy = GenerationType.TABLE)
    public Long id;

    public String handle;

    public boolean equals(Object o) {
        KeyEntity oke = (KeyEntity) o;
        return handle != null ? handle.equals(oke.handle) : oke.handle == null;
    }

    public int hashCode() {
        return handle != null ? handle.hashCode() : 0;
    }
}

价值实体:

@Entity public class ValueEntity
{
    @Id @GeneratedValue(strategy = GenerationType.TABLE)
    public Long id;

    @ManyToOne
    public KeyEntity key;

    public String value;

    public boolean equals(Object o) {
        ValueEntity ove = (ValueEntity) o;
        return key != null ? key.equals(ove.key) : ove.key == null;
    }

    public int hashCode() {
        return key != null ? key.hashCode() : 0;
    }
}

容器实体:

@Entity public class ContainerEntity
{
    @Id @GeneratedValue(strategy = GenerationType.TABLE)
    public Long id;

    @OneToMany @MapKey(name = "key")
    public Map<KeyEntity, ValueEntity> values = new HashMap<KeyEntity, ValueEntity>();
}

主要:

KeyEntity k1 = new KeyEntity();
k1.handle = "k1";
em.persist(k1);

KeyEntity k2 = new KeyEntity();
k2.handle = "k2";
em.persist(k2);

ValueEntity v1 = new ValueEntity();
v1.key = k1;
v1.value = "v1";
em.persist(v1);

ValueEntity v2 = new ValueEntity();
v2.key = k2;
v2.value = "v2";
em.persist(v2);

ContainerEntity ce = new ContainerEntity();
ce.values.put(k1, v1);
ce.values.put(k2, v2);
em.persist(ce);

// display number of values
System.out.println(ce.values.size());

// create new transaction
em.getTransaction().commit();
em.close();
em = emf.createEntityManager();
em.getTransaction().begin();

// find our container and inspect the number of values
ce = em.find(ContainerEntity.class, ce.id);
System.out.println(ce.values.size());

如果我向ContainerEntity 添加多个键值对,然后重新加载所述容器,则只会出现一个键值对。如果您查看运行上述 main 函数的输出,首先会打印 '2',然后是 '1'。

我可以看到这是因为KeyEntity.hashCode - 当插入HashMapKeyEntity.handlenull,所以所有对将具有相同的哈希码。 KeyEntity.id 此时已填充 - 如果我将此字段的哈希码作为基础,那么一切正常。此外,如果我将密钥更改为String,它会及时加载以调用hashCode

如何更改我在ContainerEntity 中的映射,以便在将KeyEntity.handle 放置在地图中时加载它,以便hashCode 可以使用它?

【问题讨论】:

  • 我觉得这很奇怪。为什么处理的引用不触发从数据库加载它?我很欣赏 KeyEntity 被延迟加载,但访问字段应该唤醒它!

标签: java hibernate jpa collections map


【解决方案1】:

herehere

... 正如 Mike 指出的那样,@MapKey 仅适用于规范 案例 Map,不适用于 Map。正确的 可嵌入值的注释将是。

IE,键应该是一个简单的基本类型(这意味着不是实体或可嵌入的),而值应该是一个实体。如果值是基本类型,@ElementCollection 可以。

但是,您需要的是键是实体类型,在这种情况下,您很不走运。

正如您所说,如果您将密钥更改为String,一切都很好,所以我建议您这样做。

【讨论】:

  • 尽管我希望有一个更好的解决方案,但似乎没有。我在 ValueEntity 中复制字符串句柄,以便可以将其用作映射键
猜你喜欢
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 2021-09-13
  • 1970-01-01
  • 2012-05-25
  • 2011-10-20
相关资源
最近更新 更多