Hibernate supports collection mapping as value type. In Hibernate collection mapping, the collection are mapped into a separate table but are not exposed as entity on the Java side. Hibernate supports following collection interfaces as value type:
- java.util.Set – java.util.HashSet is used to store value.
- java.util.SortedSet – java.util.TreeSet is used to store value.
- java.util.List – java.util.ArrayList is used to store value. Preserves the position with an index column
- Bag semantics – java.util.ArrayList is used to store valre however the position is not preserved.
- java.util.Map – java.util.HashMap is used to store value.
- java.util.SortedMap – java.util.TreeMap is used to store value.
Let’s say we want to store Phones for a Student. There are more than one Phone for a Student. So we will have two tables corresponding to Student and Phone. However we do not want to expose Phone
Table STUDENT
STUDENT_ID
...
Table PHONE
STUDENT_ID
NUMBER
...
STUDENT_ID is the foreign key and PHONE table has no primary key. To map the Phone collection as a Set in the Student Entity class
Student class
...
@org.hibernate.annotations.CollectionOfElements(targetElement = java.lang.String.class)
@JoinTable( name="PHONE",joinColumns = @JoinColumn(name="STUDENT_ID"))
@Column(name="PHONE_NO")
public Set<String> getPhones() {
...
The lifecycle of Phone is tightly coupled to Student. Also Phone table is not exposed as an entity. If the Set need to be sorted
...
@org.hibernate.annotations.CollectionOfElements(targetElement = java.lang.String.class)
@JoinTable( name="PHONE",joinColumns = @JoinColumn(name="STUDENT_ID"))
@Column(name="PHONE_NO")
@org.hibernate.annotations.Sort(type=org.hibernate.annotations.SortType.NATURAL)
public Set<String> getPhones() {
...
A comparator can also be used for Sort type.
To map the Phone collection as a list
...
@org.hibernate.annotations.CollectionOfElements
@JoinTable( name="PHONE",joinColumns = @JoinColumn(name="STUDENT_ID"))
@org.hibernate.annotations.IndexColumn(name=“INDEX_POSITION", base =1)
@Column(name="PHONE_NO")
public List<String> getPhones() {
return phones;
}
---
Here the index is mapped to a INDEX_POSITION column in the table and preserves the ordering. If the index is not given, this works like a Bag. Bag is a list but does not preserves the position.
To map Phone as a map where PHONE_NAME will act as key and PHONE_NO as value from the PHONE table. To map it
...
@org.hibernate.annotations.CollectionOfElements
@JoinTable( name="PHONE",joinColumns = @JoinColumn(name="STUDENT_ID"))
@org.hibernate.annotations.MapKey(columns = @Column(name="PHONE_NAME"))
@Column(name="PHONE_NO")
public Map<String,String> getPhones() {
...
Here the Phone table is mapped directly as a collection. We can also expose Phone as a value object. In this case define Phone as a class
@Embeddable
public class PhoneValue {
protected Student student;
protected String name;
protected String phoneNumber;
@org.hibernate.annotations.Parent
public Student getStudent() {
return student;
}
...
Also in the above case we maintain a back pointer for Student so that we can navigate from Phone to Student. To define the collection of embedded object in Student class
...
protected Collection<PhoneValue> phoneValues = new ArrayList<PhoneValue>();
@org.hibernate.annotations.CollectionOfElements
@JoinTable(name = "Student_Phone_Value",joinColumns = @JoinColumn(name="STUDENT_ID"))
@CollectionId(columns= @Column(name="STUDENT_PHONE_VALUE_ID"),
type=@org.hibernate.annotations.Type(type="long"),
generator="sequence")
public Collection<PhoneValue> getPhoneValues() {
return phoneValues;
}
...
Hibernate collection mapping is a way of mapping the collection table as values. The lifecycle of the the collections are tightly bound to the collection of the owning entity.
More write-ups on Hibernate
More write-ups on Hibernate
No comments:
Post a Comment