How do you map a "Map" in hibernate using annotations?
Using annotations how do you map a field in an entity which is a "Map" (Hashtable) of String to a given object? The object is annotated and instances of it are already stored in the hibernate databse.
I've found the syntax for definging a map with a simple key and value as such:
<class name="Foo" table="foo">
...
<map role="ages">
<key column="id"/>
<index column="name" type="string"/>
<element column="age" type="string"/>
</map>
</class>
And oddly with an entity as the key and a simple type as the value like so:
<class name="Foo" table="foo">
...
<map role="ages">
<key column="id"/>
<index-many-to-many column="person_id"
class="Person"/>
<element column="age" type="string"/>
</map>
</class>
<class name="Person" table="person">
...
<property name="name" column="name"
type="string"/>
</class>
But I don't see how to do this for a simple key to element mapping, and I don't see how to do this using annotations.
You could simply use the JPA annotation @MapKey
(note that the JPA annotation is different from the Hibernate one, the Hibernate @MapKey
maps a database column holding the map key, while the JPA's annotation maps the property to be used as the map's key).
@javax.persistence.OneToMany(cascade = CascadeType.ALL)
@javax.persistence.MapKey(name = "name")
private Map<String, Person> nameToPerson = new HashMap<String, Person>();
@CollectionOfElements(fetch = FetchType.LAZY)
@JoinTable(name = "JOINTABLE_NAME",
joinColumns = @JoinColumn(name = "id"))
@MapKey(columns = @Column(name = "name"))
@Column(name = "age")
private Map<String, String> ages = new HashMap<String, String>();
I know this question is very old but maybe this could help someone.
Other posibility is something like that:
@Entity
@Table(name = "PREFERENCE", uniqueConstraints = { @UniqueConstraint(columnNames = { "ID_DOMAIN", "ID_USER", "KEY" })})
public class Preferences {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", unique = true, nullable = false)
private Long id;
@Column(name = "ID_DOMAIN", unique = false, nullable = false")
private Long domainId;
@Column (name = "PREFERENCE_KEY")
@Enumerated(EnumType.STRING)
private PreferenceKey key;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_USER", referencedColumnName = "ID")
private User user;
}
and
@Entity
@Table(name = "USER", uniqueConstraints = { @UniqueConstraint(columnNames = { "ID_DOMAIN", "LOGIN" })})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", unique = true, nullable = false)
private Long id;
@Column(name = "ID_DOMAIN", unique = false, nullable = false")
private Long domainId;
// more fields
@ElementCollection(fetch = FetchType.LAZY)
@JoinColumns({@JoinColumn(name = "ID_USER", referencedColumnName = "ID"), @JoinColumn(name = "ID_DOMAIN", referencedColumnName = "ID_DOMAIN")})
@OneToMany(targetEntity = Preferences.class, fetch = FetchType.LAZY)
@MapKey(name = "key")
private Map<PreferenceKey, Preferences> preferencesMap;
}
That only produces two tables User and Preferences, note that PreferenceKey is unique for a User into a domain