There are times is it very comfortable using Map data structure to easily get elements by some key. For example, suppose we have in our database a “user” table, and we would like easily store and retrieve user properties.
Hibernate gives a nice solution to this issue, by using the annotation @CollectionOfElements. We will see a demonstration of using this annotation with our “user” table. Suppose we have 2 tables in out database:
- user: Contains users information. The table contains the following fields:
- user_id
- first_name
- last_name
- password
- user_property: Stores user properties. The tables contains the following fields:
- user_id
- key
- value
The structure of these 2 tables is quite simple and straight forward, therefore, we will not broaden on it.
We would like that “user_property” will be a Map containing key and value pairs, rather than being a collection in “user”. We will use @CollectionOfElements annotation in order to achieve that. This is how our User class looks like:
Note that no class exists for “user_properties” table. In this case the @CollectionOfElements mapping acts like in @ManyToMany mapping. The link to “user_properties” table is defined by the “name” property of @JoinTable. Also pay attention to the fact the @MapKey annotation that is used here belongs to “org.hibernate.annotations” and not to the “javax.persistence” package.package com.bashan.blog.hibernate;import org.hibernate.annotations.CollectionOfElements;import javax.persistence.*;import java.io.Serializable;import java.util.Map;@Entity@Table(name = "user")public class User implements Serializable {@Id@Column(name = "user_id")private Integer userId;@Column(name = "first_name")private String firstName;@Column(name = "last_name")private String last_name;@Column(name = "password")private String password;@CollectionOfElements@JoinTable(name = "user_property", joinColumns = @JoinColumn(name = "user_id"))@org.hibernate.annotations.MapKey(columns = {@Column(name = "key")})@Column(name = "value")private Map<String, String> properties;public Integer getUserId() {return userId;}public void setUserId(Integer userId) {this.userId = userId;}public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLast_name() {return last_name;}public void setLast_name(String last_name) {this.last_name = last_name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Map<String, String> getProperties() {return properties;}public void setProperties(Map<String, String> properties) {this.properties = properties;}}
You can also download this class by pressing this link.
Hi Bashan.. This post really helped me to get started with my project to persist key value pair data. Unfortunately I am unable to retrieve any User info if i pass a map of key value as a hibernate criteria.
ReplyDelete@SuppressWarnings("unchecked")
public List getEvents(final Event entity){
return this.hibernateTemplate.executeFind(new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session.createCriteria(Event.class);
criteria.add(Restrictions.between("startdatetime", entity.getStartdatetime(), entity.getEnddatetime()));
Map map = new HashMap();
map.put("key1", "value1");
criteria.add(Restrictions.eq("properties", map.values()));
return criteria.list();
}
});
}
Hi Robin,
DeleteSorry, I wrote this long time ago, so I won't be able to assist on that issue. I hope you have already managed.