Hi, I have an intermittent problem using MapKey.
The tables and data already exist, so I don't have much freedom on changing them, and I am trying to find a way to map them with Hibernate annotations. Let say that I have two tables PERSON and FAVORITE_COLOR (these are not the actual tables, just trying to simplify with a similar example): PERSON FAMILY_ID NAME HEIGHT
FAVORITE_COLOR FAMILY_ID PERSON_NAME OBJECT_TYPE FIRST_COLOR_CHOICE SECOND_COLOR_CHOICE
PERSON primary index is based on (FAMILY_ID, NAME).
The second table stores the two favorites color of a person. There is uniqueness on (FAMILY_ID, PERSON_NAME, OBJECT_TYPE). FAMILY_ID and PERSON_NAME just come from PERSON. OBJECT_TYPE describes the favorite color for a particular object, for example "shirt", "house", "car" .. So a person can have different choices for different object. OBJECT_TYPE can be NULL, in this case the colors are the person favorite colors regardless of any particular object.
So I created the following annotations (I ommited what I think is irrelevant):
@Entity @Table(name = "PERSON") @IdClass(Person.PersonPk.class) public class Person { ... @Id and other properties ...
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER) @MapKey(name = "object") @JoinColumns({ @JoinColumn(name = "FAMILY_ID", updatable=false, referencedColumnName = "FAMILY_ID"), @JoinColumn(name = "PERSON_NAME", updatable=false, referencedColumnName = "NAME") }) @AttributeOverrides({ @AttributeOverride(name = "object", column = @Column(name = "OBJECT_TYPE", updatable = false, nullable = true)) }) private Map<String, FavoriteColor> favorites;
... @Embeddable public static class PersonPk { ... } } My second entity:
@Entity @Table(name="FAVORITE_COLOR") @IdClass(FavoriteColorPk.class) @AttributeOverrides({ @AttributeOverride(name = "familyId", column = @Column(name = "FAMILY_ID", updatable = false)), @AttributeOverride(name = "name", column = @Column(name = "PERSON_NAME", updatable = false)), @AttributeOverride(name = "object", column = @Column(name = "OBJECT_TYPE", updatable = false, nullable = true)) }) public class FavoriteColor {
@Id long familyId; @Id String name; @Id String object;
@Column(name="FIRST_COLOR_CHOICE") String firstColorChoice;
@Column(name="SECOND_COLOR_CHOICE") String secondColorChoice;
... (getters and setters) ... String getObject() { return object; }
@Embeddable public static class FavoriteColorPk { ... properties of the key... } }
As long as I insert favorite colors associated with an object (not NULL), everything works fine. But I start to get intermittent errors when I insert favorite colors for no object (OBJECT_TYPE=null). The error I get is:
[04-08 14:06:04] INFO DefaultLoadEventListener [main]: Error performing load command org.hibernate.HibernateException: null index column for collection: com.acme.sdk.service.data.Person.favorites
at org.hibernate.persister.collection.AbstractCollectionPersister.readIndex(AbstractCollectionPersister.java:710) at org.hibernate.collection.PersistentMap.readFrom(PersistentMap.java:258) at org.hibernate.loader.Loader.readCollectionElement(Loader.java:1008) at org.hibernate.loader.Loader.readCollectionElements(Loader.java:646) at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:591)
a) Is it possible to use @MapKey with a property (in this case "object") that accepts nulls ?
I would assume it is possible since I don't get the error every time. But I may be missing some annotation attribute for it to always work.
b) When I add/remove elements from the map, do I need explicitly call session.saveOrUpdate() on each FavoriteColor ? Is it enough to do a saveOrUpdate(person)?
I was also trying to create the map using the FavoriteColorPk, so that it would never be null, but then I don't know what to use in the attributes of @MapKey.
private Map<FavoriteColorPk, FavoriteColor> favorites;
Help is very much appreciated.
-Jorge
|