Hibernate criteria for select into actual typesafe java objects

Hi friends,

If you know Hibernate Query Language(HQL), you will be familiar with following type of queries.

select new Family(mother, mate, offspr) from DomesticCat as mother join mother.mate as ate left join mother.kittens as offspr

It’s very useful when we retrieve some fields/properties from our entity class. The above query with “new” keyword can return a list of type “Family”. If we do not use such a keyword and specify the fields directly, a list of type Object [ ] is retrieved.

The major advantages with these type of queries are, we can easily iterate over with for-each loop, easy to display on GUI etc.

So, what my objective is that, just to write a Criteria equivalent to these type of HQL.

Here, I gonna write it in a more generic way. My example contains few number of classes, two or more enums etc. Also I include a custom comparator, which we have already discussed here.

Okay, let’s start. This is the Employee table.

db

It contains three columns namely id, fname and status. Id stands for employee id, fname for First Name of employee and status for mentioning whether the particular employee still exists or is obsolete.

Status 1 stands for LIVE employees and 0 for obsolete employees.

This is the Employee entity, Employee.java


import test.FetchType;
import java.io.Serializable;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employees", catalog = "hba")
@MappedEntity(className = "crit.pojo.Employee")
public class Employee implements Serializable {

    private long id;
    private Date dob;
    private String fname;
    private String lname;
    private int age;
    private String desgn;
    private FetchType status;

    @Column(name = "age")
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Column(name = "desgn", length = 25)
    public String getDesgn() {
        return desgn;
    }

    public void setDesgn(String desgn) {
        this.desgn = desgn;
    }

    @Column(name = "dob")
    public Date getDob() {
        return dob;
    }

    public void setDob(Date dob) {
        this.dob = dob;
    }

    @Column(name = "fname", length = 25)
    public String getFname() {
        return fname;
    }

    public void setFname(String fname) {
        this.fname = fname;
    }

    @Id
    @GeneratedValue
    @Column(name = "id")
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Column(name = "lname", length = 25)
    public String getLname() {
        return lname;
    }

    public void setLname(String lname) {
        this.lname = lname;
    }

    @Enumerated(EnumType.ORDINAL)
    public FetchType getStatus() {
        return status;
    }

    public void setStatus(FetchType status) {
        this.status = status;
    }
}

This is how the Employee entity is being mapped with MySql database, 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>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hba</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping class="crit.pojo.Employee"/>
    </session-factory>
</hibernate-configuration>

Here, I gonna make a try to retrieve a list of employees as per some searching and sorting conditions. I remind you that the following code is not destined for production, but it’s being given out just for an example.

The following example runs properly with JDK 5 or above and Hibernate 3.

This is the common Dao Class, DAO.java, where hibernate session is created.

import hba.util.HibernateUtil;
import org.hibernate.FlushMode;
import org.hibernate.Session;

public class DAO {

    private static final ThreadLocal THREAD = new ThreadLocal();

    protected DAO() {
    }

    public static Session getSession() {
        Session session = (Session) DAO.THREAD.get();
        if (session == null) {
            session = HibernateUtil.getSessionFactory().openSession();
            DAO.THREAD.set(session);
            getSession().setFlushMode(FlushMode.COMMIT);
        }
        return session;
    }

    protected static void begin() {
        getSession().beginTransaction();
    }

    protected static void commit() {
        getSession().getTransaction().commit();
    }

    protected static void rollback() {
        getSession().getTransaction().rollback();
        getSession().close();
        DAO.THREAD.set(null);
    }

    protected static void flush() {
        getSession().flush();
    }

    protected static void close() {
        getSession().close();
        DAO.THREAD.set(null);
    }
}

This is the BaseDao class, BaseDao.java, which extends above Dao class.


import crit.pojo.Employee;
import crit.pojo.UtilPojo;
import hba.dao.DAO;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.SimpleExpression;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.Transformers;

public class BaseDao extends DAO {

    public static <S> Collection<UtilPojo> load(Class<S> modelClazz, String key, String value, FetchType fetchType, SortBy sortBy, SortOrder sortOrder) {
        try {
            ProjectionList projectionList = Projections.projectionList().add(Projections.property(key).as("id")).add(Projections.property(value).as("name"));
            ResultTransformer resultTransformer = Transformers.aliasToBean(UtilPojo.class);
            Criteria criteria = getSession().createCriteria(modelClazz);
            if (fetchType == FetchType.LIVE) {
                SimpleExpression simpleExpression = Restrictions.eq(Employee.class.getDeclaredField("status").getName(), FetchType.LIVE);
                criteria.add(simpleExpression);
            }
            criteria.setProjection(projectionList);
            criteria.setResultTransformer(resultTransformer);
            List<UtilPojo> list = criteria.list();
            return CustomComparator.sort(list, sortBy, sortOrder);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return new ArrayList<UtilPojo>();
        }
    }
}

The above class contains a static utility method load(), which accepts 6 parameters, an entity class, first field of the class to be retrieved (must be of type Integer), second field of the class to be retrieved (must be of type String), the fetch type(LIVE employees/ALL employees), sortBy (ID,NAME), sortOrder (ASCENDING/DESCENDING). The method fetches those two fields from the entity class and casts those fields to UtilPojo fields/properties.

This is the UtilPojo.java


public class UtilPojo {

    private String name;
    private long id;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public UtilPojo(long id, String name) {
        this.id = id;
        this.name = name;
    }

    public UtilPojo() {
    }
}

The first enum, FetchType.java, which decides whether ALL or LIVE employees are to be retrieved.


public enum FetchType {

    ALL,
    LIVE
}

The second enum, SortBy.java, which tells by which property of entity class, the list is getting sorted. Here I give ID and NAME properties only.


public enum SortBy {

    ID("id"),
    NAME("name");
    private String value;

    public String getValue() {
        return value;
    }

    private SortBy(String value) {
        this.value = value;
    }
}

This is the third and final enum, SortOrder.java, which determines in which order (Ascending or Descending) the list is to be sorted.

public enum SortOrder {

    ASCENDING,
    DESCENDING
}

In the load() method, a list of model class, which is passed as a parameter (here the model class is Employee.java), is created, then casts the list values to a common pojo, ie. UtilPojo, then the entire is sent to the custom comparator for sorting purpose, and returns a sorted list (of type UtilPojo) to the calling method.

Here’s the CustomComparator.java, which have already been discussed in a previous post.


import crit.pojo.UtilPojo;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CustomComparator {

    private static Comparator<UtilPojo> idComparator = new Comparator<UtilPojo>() {

        public int compare(final UtilPojo pojo1, final UtilPojo pojo2) {
            return Long.valueOf(pojo1.getId()).compareTo(Long.valueOf(pojo2.getId()));
        }
    };
    private static Comparator<UtilPojo> nameComparator = new Comparator<UtilPojo>() {

        public int compare(final UtilPojo pojo1, final UtilPojo pojo2) {
            return pojo1.getName().compareTo(pojo2.getName());
        }
    };

    public static List<UtilPojo> sort(final List<UtilPojo> list, final SortBy sortBy, final SortOrder sortOrder) throws Exception {
        try {
            final Comparator<UtilPojo> comparator;
            if (sortBy == SortBy.ID) {
                comparator = idComparator;
            } else if (sortBy == SortBy.NAME) {
                comparator = nameComparator;
            } else {
                throw new IllegalArgumentException("Comparator not found for the filed, " + sortBy.getValue());
            }
            if (sortOrder == SortOrder.ASCENDING) {
                Collections.sort(list, comparator);
            } else if (sortOrder == SortOrder.DESCENDING) {
                Collections.sort(list, Collections.reverseOrder(comparator));
            } else {
                throw new IllegalArgumentException("Invalid Sort Order.");
            }
            return list;
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }
}

And finally, the last class, ListDao.java, from where a call to the load() method is emerged.


import crit.pojo.Employee;
import crit.pojo.UtilPojo;
import java.util.Collection;

public class ListDao extends BaseDao {

    public static void main(String[] args) {
        try {
            Collection<UtilPojo> collection = load(Employee.class, "id", "fname", FetchType.ALL, SortBy.ID, SortOrder.DESCENDING);
            for (UtilPojo pojo : collection) {
                System.out.println(pojo.getId() + " - " + pojo.getName());
            }
        } catch (Exception e) {
            System.out.println("Exception in List.main." + e);
        }
    }
}

Here, I tell the load() method to fetch “id” and “fname” of all employees from Employee entity, which is to be sorted by “id” in descending order.

The output will be.

 
Hibernate: select this_.id as y0_, this_.fname as y1_ from hba.employees this_
53 - Prem
41 - Tom
33 - Ram
27 - Robin
15 - Micheal
8 - Louis
5 - Kevin
4 - Deepesh
1 - Praveen

If we need a list of existing employees only, which is to be sorted by “name” in ascending order, we just want to change ListDao.java as follows.

import crit.pojo.Employee;
import crit.pojo.UtilPojo;
import java.util.Collection;

public class ListDao extends BaseDao {

    public static void main(String[] args) {
        try {
            Collection<UtilPojo> collection = load(Employee.class, "id", "fname", FetchType.LIVE, SortBy.NAME, SortOrder.ASCENDING);
            for (UtilPojo pojo : collection) {
                System.out.println(pojo.getId() + " - " + pojo.getName());
            }
        } catch (Exception e) {
            System.out.println("Exception in List.main." + e);
        }
    }
}

And the output will be.


Hibernate: select this_.id as y0_, this_.fname as y1_ from hba.employees this_ where this_.status=?
5 - Kevin
8 - Louis
1 - Praveen
53 - Prem
33 - Ram
41 - Tom

Thanks.

Hibernate many-to-one bidirectional mapping using annotation

Hi friends,

It’s all about hibernate many-to-one bidirectional mapping. Here we can discuss about country – continent relationship. That is, many countries lies in one continent. Okay, let’s start.

The DAO class, DAO.java

package hba.dao;

import hba.util.HibernateUtil;
import org.hibernate.FlushMode;
import org.hibernate.Session;

public class DAO {

    private static final ThreadLocal THREAD = new ThreadLocal();

    protected DAO() {
    }

    public static Session getSession() {
        Session session = (Session) DAO.THREAD.get();
        if (session == null) {
            session = HibernateUtil.getSessionFactory().openSession();
            DAO.THREAD.set(session);
            getSession().setFlushMode(FlushMode.COMMIT);
        }
        return session;
    }

    protected static void begin() {
        getSession().beginTransaction();
    }

    protected static void commit() {
        getSession().getTransaction().commit();
    }

    protected static void rollback() {
        getSession().getTransaction().rollback();
        getSession().close();
        DAO.THREAD.set(null);
    }

    protected static void flush() {
        getSession().flush();
    }

    protected static void close() {
        getSession().close();
        DAO.THREAD.set(null);
    }
}

The configuration file, 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>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hba</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">password1.</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping class="hba.pojo.m2o_b_continent"/>
        <mapping class="hba.pojo.m2o_b_country"/>
    </session-factory>
</hibernate-configuration>

Here’s my country POJO, m2o_b_country.java

package hba.pojo;

import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "COUNTRY", catalog = "hba")
public class m2o_b_country implements Serializable {

    private long ctry_code;
    private String ctry_name;
    private m2o_b_continent continent = new m2o_b_continent();

    @Id
    @Column(name = "CODE", length = 20)
    public long getCtry_code() {
        return ctry_code;
    }

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    public m2o_b_continent getContinent() {
        return continent;
    }

    @Column(name = "NAME", length = 20)
    public String getCtry_name() {
        return ctry_name;
    }

    public void setContinent(m2o_b_continent continent) {
        this.continent = continent;
    }

    public void setCtry_code(long ctry_code) {
        this.ctry_code = ctry_code;
    }

    public void setCtry_name(String ctry_name) {
        this.ctry_name = ctry_name;
    }
}

The continent POJO, m2o_b_continent.java

package hba.pojo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "CONTINENT", catalog = "hba")
public class m2o_b_continent implements Serializable {

    private long cnt_code;
    private String cnt_name;
    private List<m2o_b_country> countries = new ArrayList<m2o_b_country>();

    @Column(name = "NAME", length = 20)
    public String getCnt_name() {
        return cnt_name;
    }

    @Id
    @Column(name = "CODE", length = 10)
    public long getCnt_code() {
        return cnt_code;
    }

    @OneToMany(mappedBy = "continent", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    public List<m2o_b_country> getCountries() {
        return countries;
    }

    public void setCnt_code(long cnt_code) {
        this.cnt_code = cnt_code;
    }

    public void setCnt_name(String cnt_name) {
        this.cnt_name = cnt_name;
    }

    public void setCountries(List<m2o_b_country> countries) {
        this.countries = countries;
    }

    public void addCountry(m2o_b_country country) {
        country.setContinent(this);
        countries.add(country);
    }

    public m2o_b_continent(long cnt_code) {
        this.cnt_code = cnt_code;
    }

    public m2o_b_continent() {
    }
}

This is how we gonna persist both entities, the save() method of m2o_b_country_continent.java.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.m2o_b_country;
import hba.pojo.m2o_b_continent;
import java.util.ArrayList;
import java.util.List;

public class m2o_b_country_continent extends DAO {

    m2o_b_country country1 = new m2o_b_country();
    m2o_b_country country2 = new m2o_b_country();
    m2o_b_continent continent = new m2o_b_continent();
    List<m2o_b_country> countries = new ArrayList<m2o_b_country>();

    public void save() {
        try {
            begin();
            continent.setCnt_code(1);
            continent.setCnt_name("ASIA");
            country1.setCtry_code(127);
            country1.setCtry_name("INDIA");
            country1.setContinent(continent);
            country2.setCtry_code(128);
            country2.setCtry_name("JAPAN");
            country2.setContinent(continent);
            countries.add(country1);
            countries.add(country2);
            continent.setCountries(countries);
            getSession().save(country1);
            getSession().save(country2);
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) {
        try {
            m2o_b_country_continent cc = new m2o_b_country_continent();
            cc.save();
        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        }
    }
}

The above save() method outputs.

Hibernate: select m2o_b_cont_.CODE, m2o_b_cont_.NAME as NAME12_ from hba.CONTINENT m2o_b_cont_ where m2o_b_cont_.CODE=?
Hibernate: select m2o_b_coun_.CODE, m2o_b_coun_.continent_CODE as continent3_13_, m2o_b_coun_.NAME as NAME13_ from hba.COUNTRY m2o_b_coun_ where m2o_b_coun_.CODE=?
Hibernate: insert into hba.CONTINENT (NAME, CODE) values (?, ?)
Hibernate: insert into hba.COUNTRY (continent_CODE, NAME, CODE) values (?, ?, ?)
Hibernate: insert into hba.COUNTRY (continent_CODE, NAME, CODE) values (?, ?, ?)

Here, we have created two countries and one continent. We have set both countries to the continent and set the continent of each country as the above continent object.

Now, the list of countries, listCountry() method.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.m2o_b_country;
import hba.pojo.m2o_b_continent;
import java.util.ArrayList;
import java.util.List;

public class m2o_b_country_continent extends DAO {

    m2o_b_country country1 = new m2o_b_country();
    m2o_b_country country2 = new m2o_b_country();
    m2o_b_continent continent = new m2o_b_continent();
    List<m2o_b_country> countries = new ArrayList<m2o_b_country>();

    public void listCountry() {
        try {
            begin();
            List<m2o_b_country> Countries = getSession().createQuery("from m2o_b_country").list();
            for (m2o_b_country Country : Countries) {
                System.out.println("Country Code : " + Country.getCtry_code());
                System.out.println("Country Name : " + Country.getCtry_name());
                System.out.println("Continent Name : " + Country.getContinent().getCnt_name());
            }
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) {
        try {
            m2o_b_country_continent cc = new m2o_b_country_continent();
            cc.listCountry();
        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        }
    }
}

It outputs.

Hibernate: select m2o_b_coun0_.CODE as CODE13_, m2o_b_coun0_.continent_CODE as continent3_13_, m2o_b_coun0_.NAME as NAME13_ from hba.COUNTRY m2o_b_coun0_
Country Code : 127
Country Name : INDIA
Hibernate: select m2o_b_cont0_.CODE as CODE12_0_, m2o_b_cont0_.NAME as NAME12_0_ from hba.CONTINENT m2o_b_cont0_ where m2o_b_cont0_.CODE=?
Continent Name : ASIA
Country Code : 128
Country Name : JAPAN
Continent Name : ASIA

Now, the list of continents with its countries, listContinent() method.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.m2o_b_country;
import hba.pojo.m2o_b_continent;
import java.util.ArrayList;
import java.util.List;

public class m2o_b_country_continent extends DAO {

    m2o_b_country country1 = new m2o_b_country();
    m2o_b_country country2 = new m2o_b_country();
    m2o_b_continent continent = new m2o_b_continent();
    List<m2o_b_country> countries = new ArrayList<m2o_b_country>();

       public void listContinent() {
        try {
            begin();
            List<m2o_b_continent> Continents = getSession().createQuery("from m2o_b_continent").list();
            for (m2o_b_continent Continent : Continents) {
                System.out.println("Continent Name : " + Continent.getCnt_name());
                List<m2o_b_country> Countries = Continent.getCountries();
                for (m2o_b_country Country : Countries) {
                    System.out.println("Country Code : " + Country.getCtry_code());
                    System.out.println("Country Name : " + Country.getCtry_name());
                }
            }
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) {
        try {
            m2o_b_country_continent cc = new m2o_b_country_continent();
            cc.listContinent();
        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        }
    }
}

And, the output will be…

Hibernate: select m2o_b_cont0_.CODE as CODE12_, m2o_b_cont0_.NAME as NAME12_ from hba.CONTINENT m2o_b_cont0_ where m2o_b_cont0_.CODE=1252
Continent Name : ASIA
Hibernate: select countries0_.continent_CODE as continent3_1_, countries0_.CODE as CODE1_, countries0_.CODE as CODE13_0_, countries0_.continent_CODE as continent3_13_0_, countries0_.NAME as NAME13_0_ from hba.COUNTRY countries0_ where countries0_.continent_CODE=?
Country Code : 127
Country Name : INDIA
Country Code : 128
Country Name : JAPAN

Thanks.

Hibernate many-to-one unidirectional mapping using annotation

Hi friends,

Now let’s discuss hibernate many-to-one unidirectional mapping. As the name says, unidirectional mapping starts from parent entity and ends at child entity. Here, we are about to discuss many-to-one mapping. A many-to-one mapping simply equivalent to a one-to-one mapping, which we have already discussed. Click here for one-to-one unidirectional mapping and here for one-to-one bidirectional mapping. The only difference between one-to-one and many-to-one is, in former one, a parent can have exactly one child, but in latter, many parents can have the same child.

As usual, let’s start from DAO class, DAO.java.

package hba.dao;

import hba.util.HibernateUtil;
import org.hibernate.FlushMode;
import org.hibernate.Session;

public class DAO {

    private static final ThreadLocal THREAD = new ThreadLocal();

    protected DAO() {
    }

    public static Session getSession() {
        Session session = (Session) DAO.THREAD.get();
        if (session == null) {
            session = HibernateUtil.getSessionFactory().openSession();
            DAO.THREAD.set(session);
            getSession().setFlushMode(FlushMode.COMMIT);
        }
        return session;
    }

    protected static void begin() {
        getSession().beginTransaction();
    }

    protected static void commit() {
        getSession().getTransaction().commit();
    }

    protected static void rollback() {
        getSession().getTransaction().rollback();
        getSession().close();
        DAO.THREAD.set(null);
    }

    protected static void flush() {
        getSession().flush();
    }

    protected static void close() {
        getSession().close();
        DAO.THREAD.set(null);
    }
}

The configuration file, 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>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hba</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping class="hba.pojo.m2o_u_employee"/>
        <mapping class="hba.pojo.m2o_u_job"/>
    </session-factory>
</hibernate-configuration>

Here, I tell you the relationship between employee and job. Even though just a job entity in real world will not exist and will not be mapped into a relational database, I assume that it could help us for learning the concept. The relationship is, many employees can have the same job. This is true in real case.

The employee POJO, m2o_u_employee.java.

package hba.pojo;

import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEE", catalog = "hba")
public class m2o_u_employee implements Serializable {

    private long emp_id;
    private String emp_name;
    private m2o_u_job job = new m2o_u_job();

    @Id
    @GeneratedValue
    @Column(name = "EMP_ID")
    public long getEmp_id() {
        return emp_id;
    }

    @Column(name = "EMP_NAME", length = 20)
    public String getEmp_name() {
        return emp_name;
    }

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    public m2o_u_job getJob() {
        return job;
    }

    public void setEmp_id(long emp_id) {
        this.emp_id = emp_id;
    }

    public void setEmp_name(String emp_name) {
        this.emp_name = emp_name;
    }

    public void setJob(m2o_u_job job) {
        this.job = job;
    }
}

The job POJO, m2o_u_job.java.

package hba.pojo;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "JOB", catalog = "hba")
public class m2o_u_job implements Serializable {

    private long job_id;
    private String job_name;

    @Id
    @GeneratedValue
    @Column(name = "JOB_ID")
    public long getJob_id() {
        return job_id;
    }

    @Column(name = "JOB_NAME", length = 20)
    public String getJob_name() {
        return job_name;
    }

    public void setJob_id(long job_id) {
        this.job_id = job_id;
    }

    public void setJob_name(String job_name) {
        this.job_name = job_name;
    }
}

This is how we persist both entities and follow out a mapping between them, the save() method of m2o_u_emp_job.java class.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.m2o_u_employee;
import hba.pojo.m2o_u_job;

public class m2o_u_emp_job extends DAO {

    public void save() {
        try {
            begin();
            m2o_u_employee emp1 = new m2o_u_employee();
            m2o_u_employee emp2 = new m2o_u_employee();
            m2o_u_job job = new m2o_u_job();
            job.setJob_name("CEO");
            emp1.setEmp_name("John");
            emp2.setEmp_name("Sandeep");
            emp1.setJob(job);
            emp2.setJob(job);
            getSession().save(emp1);
            getSession().save(emp2);
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) throws Exception {
        new m2o_u_emp_job().save();
    }
}

This will be the output of above save() method.

Hibernate: insert into hba.JOB (JOB_NAME) values (?)
Hibernate: insert into hba.EMPLOYEE (EMP_NAME, job_JOB_ID) values (?, ?)
Hibernate: insert into hba.EMPLOYEE (EMP_NAME, job_JOB_ID) values (?, ?)

What happens here is, we are creating two employee objects and a job object, assigning each employee’s job as the new job object, then persisting both employee objects and the job object.

Thanks.

Hibernate one-to-many bidirectional mapping using annotation

Hi friends,

It’s the time to explicate hibernate one-to-many bidirectional mapping.

One-to-many means, one parent can have one or more children. A child of one particular parent can’t be the child of another parent. That’s the significant difference between one-to-many mapping and many-to-many mapping.

What bidirectional mapping over here is, we could easily find out parent entity’s properties by using child entities.

So, move on.

My DAO class, DAO.java.

package hba.dao;

import hba.util.HibernateUtil;
import org.hibernate.FlushMode;
import org.hibernate.Session;

public class DAO {

    private static final ThreadLocal THREAD = new ThreadLocal();

    protected DAO() {
    }

    public static Session getSession() {
        Session session = (Session) DAO.THREAD.get();
        if (session == null) {
            session = HibernateUtil.getSessionFactory().openSession();
            DAO.THREAD.set(session);
            getSession().setFlushMode(FlushMode.COMMIT);
        }
        return session;
    }

    protected static void begin() {
        getSession().beginTransaction();
    }

    protected static void commit() {
        getSession().getTransaction().commit();
    }

    protected static void rollback() {
        getSession().getTransaction().rollback();
        getSession().close();
        DAO.THREAD.set(null);
    }

    protected static void flush() {
        getSession().flush();
    }

    protected static void close() {
        getSession().close();
        DAO.THREAD.set(null);
    }
}

The hibernate configuration file, 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>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hba</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping class="hba.pojo.o2m_b_author"/>
        <mapping class="hba.pojo.o2m_b_book"/>
    </session-factory>
</hibernate-configuration>

The parent POJO, o2m_b_author.java.

package hba.pojo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "AUTHOR", catalog = "hba")
public class o2m_b_author implements Serializable {

    private String penName, name;
    private List<o2m_b_book> books = new ArrayList<o2m_b_book>();

    @OneToMany(mappedBy = "author", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    public List<o2m_b_book> getBooks() {
        return books;
    }

    @Column(name = "AUTH_NAME", length = 20, nullable = false)
    public String getName() {
        return name;
    }

    @Id
    @Column(name = "AUTH_PEN", length = 20)
    public String getPenName() {
        return penName;
    }

    public void setPenName(String penName) {
        this.penName = penName;
    }

    public void setBooks(List<o2m_b_book> books) {
        this.books = books;
    }

    public void setName(String name) {
        this.name = name;
    }
}

The child POJO, o2m_b_book.java.

package hba.pojo;

import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "BOOK", catalog = "hba")
public class o2m_b_book implements Serializable {

    private String isbn, name;
    private o2m_b_author author;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "BOOK_AUTHOR")
    public o2m_b_author getAuthor() {
        return author;
    }

    @Id
    @Column(name = "BOOK_ISBN", length = 20)
    public String getIsbn() {
        return isbn;
    }

    @Column(name = "BOOK_NAME", length = 20, nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public void setAuthor(o2m_b_author author) {
        this.author = author;
    }

    public o2m_b_book(String isbn, String name, o2m_b_author author) {
        this.isbn = isbn;
        this.name = name;
        this.author = author;
    }

    public o2m_b_book() {
    }
}

The save() method of o2m_b_author_book.java.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2m_b_author;
import hba.pojo.o2m_b_book;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.criterion.Expression;

public class o2m_b_author_book extends DAO {

    private List<o2m_b_book> books = new ArrayList<o2m_b_book>();
    private o2m_b_author author = new o2m_b_author();
    private o2m_b_book book1 = new o2m_b_book();
    private o2m_b_book book2 = new o2m_b_book();

    public void save() throws Exception {
        try {
            begin();
            book1.setAuthor(author);
            book1.setIsbn("8176212032");
            book1.setName("WAR AND PEACE");
            book2.setAuthor(author);
            book2.setIsbn("0981834191");
            book2.setName("THE EMPTY BOAT");
            books.add(book1);
            books.add(book2);
            author.setName("OSHO RAJNEESH");
            author.setPenName("OSHO");
            author.setBooks(books);
            getSession().save(author);
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) {
        try {
            o2m_b_author_book ab = new o2m_b_author_book();
            ab.save();
        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        }
    }
}

What happens here is, we are creating two book objects namely book1 and book2 and creating an author. After setting basic properties of books and author, we are mapping those books to the author and setting author of each book. Finally, the author object is saved. This is not the way how we have done the one-to-many unidirectional mapping. There’s one more difference that we are not creating a join table here for mapping.

The output of the above save() method will be.

Hibernate: select o2m_b_book_.BOOK_ISBN, o2m_b_book_.BOOK_AUTHOR as BOOK3_11_, o2m_b_book_.BOOK_NAME as BOOK2_11_ from hba.BOOK o2m_b_book_ where o2m_b_book_.BOOK_ISBN=?
Hibernate: select o2m_b_book_.BOOK_ISBN, o2m_b_book_.BOOK_AUTHOR as BOOK3_11_, o2m_b_book_.BOOK_NAME as BOOK2_11_ from hba.BOOK o2m_b_book_ where o2m_b_book_.BOOK_ISBN=?
Hibernate: insert into hba.AUTHOR (AUTH_NAME, AUTH_PEN) values (?, ?)
Hibernate: insert into hba.BOOK (BOOK_AUTHOR, BOOK_NAME, BOOK_ISBN) values (?, ?, ?)
Hibernate: insert into hba.BOOK (BOOK_AUTHOR, BOOK_NAME, BOOK_ISBN) values (?, ?, ?)

Another way of designing above mentioned POJO classes looks like this. This will create a join column, namely author_penName, in book table.

package hba.pojo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "AUTHOR", catalog = "hba")
public class o2m_b_author implements Serializable {

    private String penName, name;
    private List<o2m_b_book> books = new ArrayList<o2m_b_book>();

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "author_penName")
    public List<o2m_b_book> getBooks() {
        return books;
    }

    @Column(name = "AUTH_NAME", length = 20, nullable = false)
    public String getName() {
        return name;
    }

    @Id
    @Column(name = "AUTH_PEN", length = 20)
    public String getPenName() {
        return penName;
    }

    public void setPenName(String penName) {
        this.penName = penName;
    }

    public void setBooks(List<o2m_b_book> books) {
        this.books = books;
    }

    public void setName(String name) {
        this.name = name;
    }
}

package hba.pojo;

import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "BOOK", catalog = "hba")
public class o2m_b_book implements Serializable {

    private String isbn, name;
    private o2m_b_author author;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "author_penName")
    public o2m_b_author getAuthor() {
        return author;
    }

    @Id
    @Column(name = "BOOK_ISBN", length = 20)
    public String getIsbn() {
        return isbn;
    }

    @Column(name = "BOOK_NAME", length = 20, nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public void setAuthor(o2m_b_author author) {
        this.author = author;
    }

    public o2m_b_book(String isbn, String name, o2m_b_author author) {
        this.isbn = isbn;
        this.name = name;
        this.author = author;
    }

    public o2m_b_book() {
    }
}

This time we are free to eliminate reverse mapping. The new save() method looks like this.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2m_b_author;
import hba.pojo.o2m_b_book;
import java.util.ArrayList;
import java.util.List;

public class o2m_b_author_book extends DAO {

    private List<o2m_b_book> books = new ArrayList<o2m_b_book>();
    private o2m_b_author author = new o2m_b_author();
    private o2m_b_book book1 = new o2m_b_book();
    private o2m_b_book book2 = new o2m_b_book();

    public void save() throws Exception {
        try {
            begin();
            book1.setIsbn("8176212032");
            book1.setName("WAR AND PEACE");
            book2.setIsbn("0981834191");
            book2.setName("THE EMPTY BOAT");
            books.add(book1);
            books.add(book2);
            author.setName("OSHO RAJNEESH");
            author.setPenName("OSHO");
            author.setBooks(books);
            getSession().save(author);
            commit();
        } catch (Exception e) {
            rollback();
            throw new Exception("Exception in save." + e.getMessage());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) {
        try {
            o2m_b_author_book ab = new o2m_b_author_book();
            ab.save();
        } catch (Exception e) {
            System.out.println("Exception in main." + e.getMessage());
        }
    }
}

And the output will be

Hibernate: select o2m_b_book_.BOOK_ISBN, o2m_b_book_.author_penName as author3_11_, o2m_b_book_.BOOK_NAME as BOOK2_11_ from hba.BOOK o2m_b_book_ where o2m_b_book_.BOOK_ISBN=?
Hibernate: select o2m_b_book_.BOOK_ISBN, o2m_b_book_.author_penName as author3_11_, o2m_b_book_.BOOK_NAME as BOOK2_11_ from hba.BOOK o2m_b_book_ where o2m_b_book_.BOOK_ISBN=?
Hibernate: insert into hba.AUTHOR (AUTH_NAME, AUTH_PEN) values (?, ?)
Hibernate: insert into hba.BOOK (author_penName, BOOK_NAME, BOOK_ISBN) values (?, ?, ?)
Hibernate: insert into hba.BOOK (author_penName, BOOK_NAME, BOOK_ISBN) values (?, ?, ?)
Hibernate: update hba.BOOK set author_penName=? where BOOK_ISBN=?
Hibernate: update hba.BOOK set author_penName=? where BOOK_ISBN=?

See and understand the difference in output, generated by our two different approaches.
In both cases, our table design would be the very same.

Now we are retrieving author’s details, the listAuthor() method.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2m_b_author;
import hba.pojo.o2m_b_book;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.criterion.Expression;

public class o2m_b_author_book extends DAO {

    private o2m_b_author author = new o2m_b_author();

    public void listAuthor() throws Exception {
        try {
            begin();
            List<o2m_b_author> list = getSession().createCriteria(o2m_b_author.class).add(Expression.eq("penName", "OSHO")).list();
            System.out.println("List : " + list);
            for (o2m_b_author author : list) {
                System.out.println("Name of the Author : " + author.getName());
                List<o2m_b_book> authorBooks = author.getBooks();
                for (Iterator it = authorBooks.iterator(); it.hasNext();) {
                    o2m_b_book book = (o2m_b_book) it.next();
                    System.out.println("Book : " + book.getName());
                }
            }
        } catch (Exception e) {
            rollback();
           System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) {
        try {
            o2m_b_author_book ab = new o2m_b_author_book();
            ab.listAuthor();
        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());

        }
    }
}

Output of the above method will be


Hibernate: select this_.AUTH_PEN as AUTH1_10_0_, this_.AUTH_NAME as AUTH2_10_0_ from hba.AUTHOR this_ where this_.AUTH_PEN=?
List : [hba.pojo.o2m_b_author@458f41]
Name of the Author : OSHO RAJNEESH
Hibernate: select books0_.BOOK_AUTHOR as BOOK3_1_, books0_.BOOK_ISBN as BOOK1_1_, books0_.BOOK_ISBN as BOOK1_11_0_, books0_.BOOK_AUTHOR as BOOK3_11_0_, books0_.BOOK_NAME as BOOK2_11_0_ from hba.BOOK books0_ where books0_.BOOK_AUTHOR=?
Book : THE EMPTY BOAT
Book : WAR AND PEACE

Here, the advantage of bidirectional mapping arrives. Here we are querying book details. The result of the query contain author details as well.

The listBook() method.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2m_b_author;
import hba.pojo.o2m_b_book;
import java.util.Iterator;
import java.util.List;

public class o2m_b_author_book extends DAO {

    private o2m_b_author author = new o2m_b_author();

    public void listBook() throws Exception {
        try {
            begin();
            List<o2m_b_book> list = getSession().createQuery("from o2m_b_book where isbn='8176212032'").list();
            System.out.println("List : " + list);
            for (o2m_b_book book : list) {
                author = book.getAuthor();
                System.out.println("Name of the author : " + author.getName());
                List<o2m_b_book> bookList = author.getBooks();
                for (Iterator it = bookList.iterator(); it.hasNext();) {
                    book = (o2m_b_book) it.next();
                    System.out.println("Book : " + book.getName());
                }
            }
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }
    public static void main(String[] args) {
        try {
            o2m_b_author_book ab = new o2m_b_author_book();
            ab.listBook();
        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());

        }
    }
}

Output of the above method will be

Hibernate: select o2m_b_book0_.BOOK_ISBN as BOOK1_11_, o2m_b_book0_.BOOK_AUTHOR as BOOK3_11_, o2m_b_book0_.BOOK_NAME as BOOK2_11_ from hba.BOOK o2m_b_book0_ where o2m_b_book0_.BOOK_ISBN='8176212032'
Hibernate: select o2m_b_auth0_.AUTH_PEN as AUTH1_10_0_, o2m_b_auth0_.AUTH_NAME as AUTH2_10_0_ from hba.AUTHOR o2m_b_auth0_ where o2m_b_auth0_.AUTH_PEN=?
List : [hba.pojo.o2m_b_book@6a3960]
Name of the author : OSHO RAJNEESH
Hibernate: select books0_.BOOK_AUTHOR as BOOK3_1_, books0_.BOOK_ISBN as BOOK1_1_, books0_.BOOK_ISBN as BOOK1_11_0_, books0_.BOOK_AUTHOR as BOOK3_11_0_, books0_.BOOK_NAME as BOOK2_11_0_ from hba.BOOK books0_ where books0_.BOOK_AUTHOR=?
Book : THE EMPTY BOAT
Book : WAR AND PEACE

Now you could see that, by querying a book using its isbn number, we could easily get its author details as well as the details of other books written by that author.

Thanks.

Hibernate one-to-many unidirectional mapping using annotation

Hi friends,

Welcome back to hibernate mapping..

Here, we can discuss more about hibernate one-to-many unidirectional mapping with an example. After reading this post, you will definitely get to know how to code a hibernate one-to-many unidirectional mapping program.

Now come to the point. One-to-many mapping means, one entity in parent table can have one or more children in child table. To be in detail, By querying parent, we will also get its children’s properties. Please note that this will only happen if the fetch type is EAGER. If it LAZY, we would have to explicitly query the children.

Why it is called unidirectional, because, we can get child details when we just query its parent, but will not happen vice versa, ie; we could not find out a parent by giving child details.

Here, we can talk over an one-to-many unidirectional mapping example. I use LAZY fetching over here.

if you want to recall one-to-one unidirectional and bidirectional mapping, just drive around and come back.

So, let’s start.

Here’s my DAO class, DAO.java.

package hba.dao;

import hba.util.HibernateUtil;
import org.hibernate.FlushMode;
import org.hibernate.Session;

public class DAO {

    private static final ThreadLocal THREAD = new ThreadLocal();

    protected DAO() {
    }

    public static Session getSession() {
        Session session = (Session) DAO.THREAD.get();
        if (session == null) {
            session = HibernateUtil.getSessionFactory().openSession();
            DAO.THREAD.set(session);
            getSession().setFlushMode(FlushMode.COMMIT);
        }
        return session;
    }

    protected static void begin() {
        getSession().beginTransaction();
    }

    protected static void commit() {
        getSession().getTransaction().commit();
    }

    protected static void rollback() {
        getSession().getTransaction().rollback();
        getSession().close();
        DAO.THREAD.set(null);
    }

    protected static void flush() {
        getSession().flush();
    }

    protected static void close() {
        getSession().close();
        DAO.THREAD.set(null);
    }
}

The hibernate configuration file, hibernate.cfb.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>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hba</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping class="hba.pojo.o2m_u_blog"/>
        <mapping class="hba.pojo.o2m_u_post"/>
    </session-factory>
</hibernate-configuration>

My parent POJO, o2m_u_blog.java.

package hba.pojo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "BLOG", catalog = "hba")
public class o2m_u_blog implements Serializable {

    private long blg_id;
    private String blg_name;
    private List<o2m_u_post> blg_posts = new ArrayList<o2m_u_post>();

    @Id
    @GeneratedValue
    @Column(name = "BLG_ID")
    public long getBlg_id() {
        return blg_id;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinTable(name = "BLOG_POST", joinColumns = {
        @JoinColumn(name = "BLG_ID")}, inverseJoinColumns = {
        @JoinColumn(name = "PST_ID")})
    public List<o2m_u_post> getBlg_posts() {
        return blg_posts;
    }

    @Column(name = "BLG_NAME", length = 20)
    public String getBlg_name() {
        return blg_name;
    }

    public void setBlg_id(long blg_id) {
        this.blg_id = blg_id;
    }

    public void setBlg_name(String blg_name) {
        this.blg_name = blg_name;
    }

    public void setBlg_posts(List<o2m_u_post> blg_posts) {
        this.blg_posts = blg_posts;
    }

    public o2m_u_blog(long blg_id) {
        this.blg_id = blg_id;
    }

    public o2m_u_blog() {
    }
}

The child POJO, o2m_u_post.java.

package hba.pojo;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "POST", catalog = "hba")
public class o2m_u_post implements Serializable {

    private long pst_id;
    private String pst_name;

    @Id
    @GeneratedValue
    @Column(name = "PST_ID")
    public long getPst_id() {
        return pst_id;
    }

    @Column(name = "PST_NAME", length = 20)
    public String getPst_name() {
        return pst_name;
    }

    public void setPst_id(long pst_id) {
        this.pst_id = pst_id;
    }

    public void setPst_name(String pst_name) {
        this.pst_name = pst_name;
    }

    public o2m_u_post(String pst_name) {
        this.pst_name = pst_name;
    }

    public o2m_u_post(long pst_id) {
        this.pst_id = pst_id;
    }

    public o2m_u_post() {
    }
}

This is my business class, o2m_u_blg_pst.java, in which I have written methods for saving and listing data.Here’s the save() method.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2m_u_blog;
import hba.pojo.o2m_u_post;
import java.util.ArrayList;
import java.util.List;

public class o2m_u_blg_pst extends DAO {

    public void save() {
        try {
            begin();
            List<o2m_u_post> posts = new ArrayList<o2m_u_post>();
            o2m_u_blog blog = new o2m_u_blog();
            posts.add(new o2m_u_post("Struts 2"));
            posts.add(new o2m_u_post("Hibernate 3"));
            blog.setBlg_name("My Java");
            blog.setBlg_posts(posts);
            getSession().save(blog);
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

    public static void main(String[] args) {
        try {
            new o2m_u_blg_pst().save();
        } catch (Exception e) {
            System.out.println("Exception in main." + e.getMessage());
        }
    }
}

Here, I’ve created two posts about “Struts 2” and “Hibernate 3” and put those posts under a blog “My Java”. Finally I’ve saved my blog. It will also be saving two posts and automatically creating a new join table with mappings between blog and posts.

This will be the output when I execute save() method.

Hibernate: insert into hba.BLOG (BLG_NAME) values (?)
Hibernate: insert into hba.POST (PST_NAME) values (?)
Hibernate: insert into hba.POST (PST_NAME) values (?)
Hibernate: insert into BLOG_POST (BLG_ID, PST_ID) values (?, ?)
Hibernate: insert into BLOG_POST (BLG_ID, PST_ID) values (?, ?)

This is how I am retrieving my data, the list() method.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2m_u_blog;
import hba.pojo.o2m_u_post;
import java.util.ArrayList;
import java.util.List;

public class o2m_u_blg_pst extends DAO {

    public void list() {
        try {
            List<o2m_u_blog> blogs = getSession().createQuery("from o2m_u_blog").list();
            for (o2m_u_blog blog : blogs) {
                System.out.println("Blog Name: " + blog.getBlg_name());
                List<o2m_u_post> posts = blog.getBlg_posts();
                for (o2m_u_post post : posts) {
                    System.out.println("Post Name: " + post.getPst_name());
                }
            }
        } catch (Exception e) {
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        }
    }

    public static void main(String[] args) {
        try {
            new o2m_u_blg_pst().list();
        } catch (Exception e) {
            System.out.println("Exception in main." + e.getMessage());
        }
    }
}

This will be the output.

Hibernate: select o2m_u_blog0_.BLG_ID as BLG1_2_, o2m_u_blog0_.BLG_NAME as BLG2_2_ from hba.BLOG o2m_u_blog0_
Blog Name: My Java
Hibernate: select blg_posts0_.BLG_ID as BLG1_1_, blg_posts0_.PST_ID as PST2_1_, o2m_u_post1_.PST_ID as PST1_3_0_, o2m_u_post1_.PST_NAME as PST2_3_0_ from BLOG_POST blg_posts0_ left outer join hba.POST o2m_u_post1_ on blg_posts0_.PST_ID=o2m_u_post1_.PST_ID where blg_posts0_.BLG_ID=?
Post Name: Struts 2
Post Name: Hibernate 3

Thanks.