简体   繁体   中英

JPA2.0 map key is not stored

I have a simple JPA mapping example including a map. A TestEntity has a map of SubEntity-Objects and some keys. I would have expected that the map keys are stored. Instead they are null. Here is the code:

@Entity
public class TestEntity {

    @OneToMany
    public Map<String, SubEntity> map = new HashMap<String, SubEntity>();

    @Id
    @GeneratedValue(strategy = AUTO)
    protected long id;

    public String name;

    public TestEntity() {
    }

    public TestEntity(String name) {
        this.name = name;
    }
}

This is the subentity:

@Entity
public class SubEntity {

    @Id
    @GeneratedValue(strategy = AUTO)
    protected long id;

    public SubEntity() {
    }

    String subEntityName;

    public SubEntity(String name) {
        this.subEntityName = name;
    }
}

And here is the test code:

EntityManager em = EntityManagerService.getEntityManager();
em.getTransaction().begin();

for (int i = 0; i < 10; i++) {
    TestEntity e = new TestEntity("MyNameIs" + i);
    for (int j = 0; j < 8; j++) {
        SubEntity se = new SubEntity("IamNo" + j + "." + i);
        e.map.put("Key" + i * 100 + j, se);
        em.persist(se);
    }
    em.persist(e);
}

em.getTransaction().commit();

All Objects are created and stored. Just the key values in the mapping table are all null. Where is my mistake? I am using JPA2 with eclipselink2.4.1 and Derby 10.

JPA 2.0 supports collections of primitives through the @ElementCollection annotation that you can use in conjunction with the support of java.util.Map collections. Something like this should work:

@Entity
public class Example {
    @Id long id;
    // ....
    @ElementCollection
    @MapKeyColumn(name="name")
    @Column(name="value")
    @CollectionTable(name="example_attributes", joinColumns=@JoinColumn(name="example_id"))
    Map<String, String> attributes = new HashMap<String, String>(); // maps from attribute name to value

}

Use @MapKey to specify an attribute of the target entity (SubEntity) that serves as the key for the map.

Or use @MapKeyColumn to specify that the key must be stored in an additional column, not mapped in SubEntity.

The javadoc provides examples.

Finally I found the explanation: It is a bug in eclipselink . The bug is reported for version 2.3.1. I have used 2.4.1 and it does not seem to be fixed. Here is a related question . The first answer helps a lot: Although the defaults for @JoinTable and @MapKeyColumn create the right tabels and columns, just add them explicitly. My example from above looks like that now:

@Entity
public class TestEntity {

    @OneToMany
    // add these annotations for a work-around
    @JoinTable(name="TESTENTITY_SUBENTITY")
    @MapKeyColumn(name = "MAP_KEY", table="TESTENTITY_SUBENTITY")
    public Map<String, SubEntity> map = new HashMap<String, SubEntity>();

    @Id
    @GeneratedValue(strategy = AUTO)
    protected long id;

    public String name;

    public TestEntity() {
}

    public TestEntity(String name) {
        this.name = name;
    }
}

With these two additional lines the keys are stored. The created tables look like that .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM