Карта JPA с ключом сущности и значением сущности

Key Entity:

@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;
    }
}

Value Entity:

@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;
    }
}

Container Entity:

@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>();
}

Main:

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 , а затем перезагрузите указанный контейнер, будет присутствовать только одна пара "ключ-значение". Если вы посмотрите на результат выполнения вышеупомянутой основной функции, сначала будет напечатано «2», а затем «1».

Я вижу, что это из-за KeyEntity.hashCode - при вставке в HashMap KeyEntity.handle имеет значение null , поэтому все пары будет иметь такой же хэш-код. KeyEntity.id заполняется на этом этапе - если я основываю хэш-код на этом поле, все работает. Также, если я изменю ключ на String , он будет загружен вовремя для вызовов hashCode .

Как я могу изменить свои сопоставления в ContainerEntity , чтобы KeyEntity.handle загружался при размещении внутри карты, чтобы hashCode мог его использовать?

6
задан rhollencamp 4 January 2012 в 20:00
поделиться