Thursday, July 11, 2013

Hibernate Mappings for java Collections using XML and Annotations



Mapping Collections via *.hbm.xml and @ Annotations


Before start giving details just note some basics about various collections
1.      Java.util.List :

i.                     Contains heterogeneous elements.

ii.                   Elements are placed as per insertion order.

iii.                  Can be accessed via index, where set maintain its index.

2.      Java.util.Set :

ii.                   Contains heterogeneous elements.

iii.                  Elements are placed in random order.

iv.                 Can’t be accessed via index.

3.      Java.util.Map :

i.                     Contains key-value pairs.

ii.                   Contains heterogeneous values, can contain heterogeneous values.

iii.                  Elements are placed as per key.

iv.                 Can be accessed via index, here key act as an index.

4.      Arrays :

i.                     Can contain only homogeneous values.

ii.                   Elements are placed as per insertion order.

iii.                  Can be accessed via index where index is internally maintained.


How to map collection to database in hibernate :

As each collection can hold multiple values i.e if a person is having emails, so a person can hold multiple email id, while mapping these things to database we will be having problem that a column can contain a single value.

In above case if we are having a single table named ‘PERSON’ it will raise problem of having multiple email values for ‘EMAIL’ column.

So to map collection values, we have to create a separate table for column having multiple values( EMAIL column will be carved out from PERSON table and a fresh new table named EMAILS will be created to hold EMAIL values)  and we have to link the primary table and child table ( PERSON – EMAILS ) using foreign key constraint.

As few Collection type also maintains their order so to maintain that we have to keep a column named INDEX in database table.



Collection Type
*.hbm.xml
Annotation
List
<list name="emails" table="emails">
     <key column="sid"/>
     <index column=”idx”/>
     <element column="email" type="string"/>
</list>
@CollectionOfElements
@JoinTable(name="emails", joinColumns=@JoinColumn(name="sid"))
@IndexColumn(name="idx")
@Column(name="email")
Set
<set name="phones" table="phones">
                        <key column="sid"/>
                        <element column ="phones" type="long"/>
             </set>
@CollectionOfElements
@JoinTable(name="phones", joinColumns=@JoinColumn(name="sid"))
@Column(name="phone")
Set<Long> phones;
Map
<map name="refs" table="refs">
    <key column="sid"/>
    <index column="rname" type="string"/>
    <element column="rphone" type="string"/>
</map>
@CollectionOfElements
@JoinTable(name="refs", joinColumns=@JoinColumn(name="sid"))
@IndexColumn(name="rname")
@Column(name="rphone")
Map<String,String> refs;
Arrays
<array name="courses" table="courses">
    <key column="sid"/>
    <index column="idx"/>
    <element column="cname" type="string"/>
</array>
@CollectionOfElements
@JoinTable(name="courses", joinColumns=@JoinColumn(name="sid"))
@IndexColumn(name="idx")
@Column(name="course")
String [] courses;






Let’s See Examples for both type of mappings:

1. Mapping various Collections via *.hbm.xml


Points to ponder :
I am asking  hibernate to create tables for me so no need to create tables separately.

I am using MySQL and database named ‘testdb2’. Please create a database ‘testdb2’ using command


Create database testdb2;


Project Structure:

                                     









 Hibernate.cfg.xml :


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC

                        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

                        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory name="collectionMapping">

        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="hibernate.connection.password">admin</property>

        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/testdb2</property>

        <property name="hibernate.connection.username">root</property>

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <property name="hbm2ddl.auto">update<?xml-stylesheet type="text/xsl" href=""?></property>

        <mapping resource="com/sushil/hibernate/model/student.hbm.xml"/>

    </session-factory>

     

</hibernate-configuration>

student.hbm.xml
<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC

 "-//Hibernate/Hibernate Mapping DTD//EN"

 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">



 <hibernate-mapping package="com.sushil.hibernate.model">



 <class name="Student" table="student_details">

             <id name="sid">

                        <generator class="increment"/>

             </id>

             

             <property name="sname"/>

             <property name="dob"/>

             <property name="qual" />

             

             <array name="courses" table="courses">

                        <key column="sid"/>

                        <index column="idx"/>

                        <element column="cname" type="string"/>

             </array>

             

             <list name="emails" table="emails">

                        <key column="sid"/>

                        <index/>

                        <element column="email" type="string"/>

             </list>

             

             <bag name="marks" table="marks">

                        <key column="sid"/>

                        <element column="marks" type="int"/>

             </bag>

             

             <set name="phones" table="phones">

                        <key column="sid"/>

                        <element column ="phones" type="long"/>

             </set>



            <map name="refs" table="refs">

                        <key column="sid"/>

                        <index column="rname" type="string"/>

                        <element column="rphone" type="string"/>

            </map>

 </class>

 </hibernate-mapping>





Student.java



package com.sushil.hibernate.model;



import java.util.*;



public class Student {



            int sid;

            String sname;

            String dob;

            String qual;

            String [] courses;

            List<String> emails;

            List<Integer> marks;

            Set<Long> phones;

            Map<String,String> refs;



            public Student() {}



            public Student(String sname, String dob, String qual, String[] courses,

                                    List<String> emails, List<Integer> marks, Set<Long> phones,

                                    Map<String, String> refs) {

                        super();

                        this.sname = sname;

                        this.dob = dob;

                        this.qual = qual;

                        this.courses = courses;

                        this.emails = emails;

                        this.marks = marks;

                        this.phones = phones;

                        this.refs = refs;

            }

            public int getSid() {

                        return sid;

            }

            public void setSid(int sid) {

                        this.sid = sid;

            }

            public String getSname() {

                        return sname;

            }

            public void setSname(String sname) {

                        this.sname = sname;

            }

            public String getDob() {

                        return dob;

            }

            public void setDob(String dob) {

                        this.dob = dob;

            }

            public String getQual() {

                        return qual;

            }

            public void setQual(String qual) {

                        this.qual = qual;

            }

            public String[] getCourses() {

                        return courses;

            }

            public void setCourses(String[] courses) {

                        this.courses = courses;

            }

            public List<String> getEmails() {

                        return emails;

            }

            public void setEmails(List<String> emails) {

                        this.emails = emails;

            }

            public List<Integer> getMarks() {

                        return marks;

            }

            public void setMarks(List<Integer> marks) {

                        this.marks = marks;

            }

            public Set<Long> getPhones() {

                        return phones;

            }

            public void setPhones(Set<Long> phones) {

                        this.phones = phones;

            }



            public Map<String, String> getRefs() {

                        return refs;

            }



            public void setRefs(Map<String, String> refs) {

                        this.refs = refs;

            }



            @Override

            public String toString() {

                        return "Student [sid=" + sid + ", sname=" + sname + ", dob=" + dob

                                                + ", qual=" + qual + ", courses=" + Arrays.toString(courses)

                                                + ", emails=" + emails + ", marks=" + marks + ", phones="

                                                + phones + ", refs=" + refs + "]";

            }



}





HibernateUtil.java



package com.sushil.hibernate.util;



import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;



public class HibernateUtil {

           

            static SessionFactory fact;

           

            static {

           

            Configuration cfg=new Configuration();

            cfg=cfg.configure();

            fact=cfg.buildSessionFactory();

           

            }

           

            public static SessionFactory getFactory(){

                        return fact;

            }

           

}



Client.java



package com.sushil.hibernate.client;



import java.util.*;

import org.hibernate.*;

import com.sushil.hibernate.model.Student;

import com.sushil.hibernate.util.HibernateUtil;



public class Client {

            public static void main(String[] args) {

                       SessionFactory fact=HibernateUtil.getFactory();

                       List<String> emails =new ArrayList<String>();

                        emails.add("a@hi.com");

                        emails.add("b@hi.com");

                        emails.add("c@hi.com");

                        emails.add("d@hi.com");

                        List<Integer> marks =new ArrayList<Integer>();

                        marks.add(20);

                        marks.add(30);

                        marks.add(40);

                        String courses[] = {"Core Java","Spring","Hibernate","Data Structure"};

                        Set<Long> phones=new HashSet<Long>();

                        phones.add(93456198291L);

                        phones.add(87634178191L);

                        phones.add(98561432671L);

                        Map<String,String> refs=new HashMap<String,String>();

                        refs.put("aaa", "bbb");

                        refs.put("ccc", "ddd");

                        refs.put("eee", "fff");

                                               

                        try{

                        Session ses=fact.openSession();

                        Transaction tx=ses.beginTransaction();

               Student st= new Student("Sushil", "12-07-1985", "MCA", courses, emails, marks, phones, refs);

                        ses.save(st);

                        tx.commit();

                       }catch( Exception e){

                                    e.printStackTrace();

                        }

                       System.out.print("All Tables Created");

            }

}



Ouptut :




2. Mapping various Collections via @ Annotations



Project Structure:



                                



Hibernate.cfg.xml



<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC

                        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

                        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory name="collectionMapping">

        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="hibernate.connection.password">admin</property>

        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/HiberAnnotestdb</property>

        <property name="hibernate.connection.username">root</property>

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <property name="hbm2ddl.auto">update<?xml-stylesheet type="text/xsl" href=""?></property>

        <mapping class="com.sushil.hibernate.model.Student"/>

    </session-factory>

     

</hibernate-configuration>





Student.java



package com.sushil.hibernate.model;



import java.util.*;



import javax.persistence.*;



import org.hibernate.annotations.CollectionOfElements;

import org.hibernate.annotations.IndexColumn;



@Entity

@Table(name="student")

public class Student {



            @Id

            @GeneratedValue(strategy=GenerationType.AUTO)

            @Column(name="sid")

            int sid;

           

            @Column(name="sname")

            String sname;

           

            @Column(name="dob")

            String dob;

           

            @Column(name="qual")

            String qual;

           

            @CollectionOfElements

            @JoinTable(name="courses", joinColumns=@JoinColumn(name="sid"))

            @IndexColumn(name="idx")

            @Column(name="course")

            String [] courses;

           

            @CollectionOfElements

            @JoinTable(name="emails", joinColumns=@JoinColumn(name="sid"))

            @IndexColumn(name="idx")

            @Column(name="email")

            List<String> emails;

           

            @CollectionOfElements

            @JoinTable(name="marks", joinColumns=@JoinColumn(name="sid"))

            @IndexColumn(name="idx")

            @Column(name="marks")

            List<Integer> marks;

           

           

            @CollectionOfElements

            @JoinTable(name="phones", joinColumns=@JoinColumn(name="sid"))

            @Column(name="phone")

            Set<Long> phones;

           

            @CollectionOfElements

            @JoinTable(name="refs", joinColumns=@JoinColumn(name="sid"))

            @IndexColumn(name="rname")

            @Column(name="rphone")

            Map<String,String> refs;

           

public Student() { }



            public Student(String sname, String dob, String qual, String[] courses,

                                    List<String> emails, List<Integer> marks, Set<Long> phones,

                                    Map<String, String> refs) {

                        super();

                        this.sname = sname;

                        this.dob = dob;

                        this.qual = qual;

                        this.courses = courses;

                        this.emails = emails;

                        this.marks = marks;

                        this.phones = phones;

                        this.refs = refs;

            }

            public int getSid() {

                        return sid;

}

            public void setSid(int sid) {

                        this.sid = sid;

            }

            public String getSname() {

                        return sname;

            }

            public void setSname(String sname) {

                        this.sname = sname;

            }

            public String getDob() {

                        return dob;

            }

            public void setDob(String dob) {

                        this.dob = dob;

            }

            public String getQual() {

                        return qual;

            }

public void setQual(String qual) {

                        this.qual = qual;

            }

            public String[] getCourses() {

                        return courses;

            }

            public void setCourses(String[] courses) {

                        this.courses = courses;

            }

            public List<String> getEmails() {

                        return emails;

            }

            public void setEmails(List<String> emails) {

                        this.emails = emails;

            }

            public List<Integer> getMarks() {

                        return marks;

            }

            public void setMarks(List<Integer> marks) {

                        this.marks = marks;

            }

            public Set<Long> getPhones() {

                        return phones;

            }

            public void setPhones(Set<Long> phones) {

                        this.phones = phones;

            }

            public Map<String, String> getRefs() {

                        return refs;

            }

            public void setRefs(Map<String, String> refs) {

                        this.refs = refs;

            }



            @Override

            public String toString() {

                        return "Student [sid=" + sid + ", sname=" + sname + ", dob=" + dob

                                                + ", qual=" + qual + ", courses=" + Arrays.toString(courses)

                                                + ", emails=" + emails + ", marks=" + marks + ", phones="

                                                + phones + ", refs=" + refs + "]";

            }

}



HibernateUtil.java



package com.sushil.hibernate.util;



import org.hibernate.SessionFactory;

import org.hibernate.cfg.AnnotationConfiguration;

import org.hibernate.cfg.Configuration;



public class HibernateUtil {

           

            static SessionFactory fact;

           

            static {

           

            Configuration cfg=new AnnotationConfiguration();

            cfg=cfg.configure();

            fact=cfg.buildSessionFactory();

            }

           

            public static SessionFactory getFactory(){

                        return fact;

            }

           

}





Client.java



Same as in previous example.



Ouput :