Hibernate one-to-one bidirectional mapping using annotation

Hi friends,

Here i’m gonna tell you something about Hibernate mapping, Now, it’s all about one-to-one bidirectional mapping. Bidirectional mapping means, the child knows its parent’s properties/characteristics. Simply, we can say, from child’s point of view, it can easily identify who its parent is.

Here, i’m exploring a bidirectional mapping between a sim and a mobile. I just assume each phone is having exactly one sim and vice versa, even though it’s not practical in real world.

Here’s the DAO class, DAO.java.

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.o2o_b_mobile"/>
        <mapping class="hba.pojo.o2o_b_sim"/>
    </session-factory>
</hibernate-configuration>

Here’s the mobile POJO, o2o_b_mobile.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.OneToOne;
import javax.persistence.Table;

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

    private String imei, model;
    private o2o_b_sim sim;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "MOB_SIM")
    public o2o_b_sim getSim() {
        return sim;
    }

    @Column(name = "MOB_MODEL", length = 20, nullable = false)
    public String getModel() {
        return model;
    }

    @Id
    @Column(name = "MOB_IMEI", length = 10, nullable = false)
    public String getImei() {
        return imei;
    }

    public void setSim(o2o_b_sim sim) {
        this.sim = sim;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public void setModel(String model) {
        this.model = model;
    }
}

Download mobile POJO

Here’s the sim POJO, o2o_b_sim.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.OneToOne;
import javax.persistence.Table;


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

    private String no;
    private String company;
    private o2o_b_mobile mobile;

    @OneToOne(mappedBy = "sim", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    public o2o_b_mobile getMobile() {
        return mobile;
    }

    @Column(name = "SIM_COMPANY", length = 20, nullable = false)
    public String getCompany() {
        return company;
    }

    @Id
    @Column(name = "SIM_NO", length = 20)
    public String getNo() {
        return no;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public void setMobile(o2o_b_mobile mobile) {
        this.mobile = mobile;
    }

    public void setNo(String no) {
        this.no = no;
    }
}

Download sim POJO

Here’s the save() method of o2o_b_mobile_sim.java.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2o_b_mobile;
import hba.pojo.o2o_b_sim;

public class o2o_b_mobile_sim extends DAO {

    private o2o_b_mobile mobile = new o2o_b_mobile();
    private o2o_b_sim sim = new o2o_b_sim();

    public void save() throws Exception {
        try {
            begin();
            sim.setNo("9496351113");
            sim.setCompany("BSNL");
            mobile.setImei("123456789");
            mobile.setModel("SAMSUNG CORBY");
            mobile.setSim(sim);
            getSession().save(mobile);
            commit();
        } catch (Exception e) {
            rollback();
            throw new Exception("Exception in save : " + e.getMessage());
        } finally {
            flush();
            close();
        }
    }

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

Download the save() method

The output of the above save() method will be

Hibernate: select o2o_b_sim_.SIM_NO, o2o_b_sim_.SIM_COMPANY as SIM2_9_ from hba.SIM o2o_b_sim_ where o2o_b_sim_.SIM_NO=?
Hibernate: insert into hba.SIM (SIM_COMPANY, SIM_NO) values (?, ?)
Hibernate: insert into hba.MOBILE (MOB_MODEL, MOB_SIM, MOB_IMEI) values (?, ?, ?)

Here, the join column will be created on mobile side.

Another design implementation looks like this.

The mobile POJO class, o2o_b_mobile.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.OneToOne;
import javax.persistence.Table;

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

    private String imei, model;
    private o2o_b_sim sim;

    @OneToOne(mappedBy = "mobile", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "MOB_IMEI")
    public o2o_b_sim getSim() {
        return sim;
    }

    @Column(name = "MOB_MODEL", length = 20, nullable = false)
    public String getModel() {
        return model;
    }

    @Id
    @Column(name = "MOB_IMEI", length = 10, nullable = false)
    public String getImei() {
        return imei;
    }

    public void setSim(o2o_b_sim sim) {
        this.sim = sim;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public void setModel(String model) {
        this.model = model;
    }
}

The next POJO class, o2o_b_sim.java.

package hba.pojo;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;

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

    private String no;
    private String company;
    private o2o_b_mobile mobile;

    @OneToOne(fetch = FetchType.EAGER)
    @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    public o2o_b_mobile getMobile() {
        return mobile;
    }

    @Column(name = "SIM_COMPANY", length = 20, nullable = false)
    public String getCompany() {
        return company;
    }

    @Id
    @Column(name = "SIM_NO", length = 20)
    public String getNo() {
        return no;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public void setMobile(o2o_b_mobile mobile) {
        this.mobile = mobile;
    }

    public void setNo(String no) {
        this.no = no;
    }
}

The save() method

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2o_b_mobile;
import hba.pojo.o2o_b_sim;

public class o2o_b_mobile_sim extends DAO {

    private o2o_b_mobile mobile = new o2o_b_mobile();
    private o2o_b_sim sim = new o2o_b_sim();

    public void save() throws Exception {
        try {
            begin();
            sim.setNo("9496351113");
            sim.setCompany("BSNL");
            mobile.setImei("123456789");
            mobile.setModel("SAMSUNG CORBY");
            mobile.setSim(sim);
            sim.setMobile(mobile);
            getSession().save(mobile);
            commit();
        } catch (Exception e) {
            rollback();
            throw new Exception("Exception in save : " + e.getMessage());
        } finally {
            flush();
            close();
        }
    }

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

Here, we have mapped sim to mobile and mobile to sim, and the join column will be created on sim side. The output of the above save() method will be

Hibernate: select o2o_b_sim_.SIM_NO, o2o_b_sim_.SIM_COMPANY as SIM2_9_, o2o_b_sim_.mobile_MOB_IMEI as mobile3_9_ from hba.SIM o2o_b_sim_ where o2o_b_sim_.SIM_NO=?
Hibernate: insert into hba.MOBILE (MOB_MODEL, MOB_IMEI) values (?, ?)
Hibernate: insert into hba.SIM (SIM_COMPANY, mobile_MOB_IMEI, SIM_NO) values (?, ?, ?)

Retrieving mobile details, the listMobile() method.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2o_b_mobile;
import hba.pojo.o2o_b_sim;
import java.util.List;

public class o2o_b_mobile_sim extends DAO {

    public void listMobile() {
        try {
            begin();
            List<o2o_b_mobile> mobiles = getSession().createCriteria(o2o_b_mobile.class).list();
            for (o2o_b_mobile Mobile : mobiles) {
                System.out.println("IMEI: " + Mobile.getImei());
                System.out.println("Model: " + Mobile.getModel());
                o2o_b_sim Sim = Mobile.getSim();
                System.out.println("Sim No: " + Sim.getNo());
                System.out.println("Sim Company: " + Sim.getCompany());
            }
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

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

The output will be

Hibernate: select this_.MOB_IMEI as MOB1_8_1_, this_.MOB_MODEL as MOB2_8_1_, this_.MOB_SIM as MOB3_8_1_, o2o_b_sim2_.SIM_NO as SIM1_9_0_, o2o_b_sim2_.SIM_COMPANY as SIM2_9_0_ from hba.MOBILE this_ left outer join hba.SIM o2o_b_sim2_ on this_.MOB_SIM=o2o_b_sim2_.SIM_NO
Hibernate: select o2o_b_mobi0_.MOB_IMEI as MOB1_8_1_, o2o_b_mobi0_.MOB_MODEL as MOB2_8_1_, o2o_b_mobi0_.MOB_SIM as MOB3_8_1_, o2o_b_sim1_.SIM_NO as SIM1_9_0_, o2o_b_sim1_.SIM_COMPANY as SIM2_9_0_ from hba.MOBILE o2o_b_mobi0_ left outer join hba.SIM o2o_b_sim1_ on o2o_b_mobi0_.MOB_SIM=o2o_b_sim1_.SIM_NO where o2o_b_mobi0_.MOB_SIM=?
IMEI: 123456789
Model: SAMSUNG CORBY
Sim No: 9496351113
Sim Company: BSNL

Retrieving sim details, the listSim() method, it contains mobile details as well.

package hba.biz;

import hba.dao.DAO;
import hba.pojo.o2o_b_mobile;
import hba.pojo.o2o_b_sim;
import java.util.List;

public class o2o_b_mobile_sim extends DAO {

    public void listSim() throws Exception {
        try {
            begin();
            List<o2o_b_sim> sims = getSession().createQuery("from o2o_b_sim where no=:no").setString("no", "9496351113").list();
            System.out.println("List : " + sims);
            for (o2o_b_sim Sim : sims) {
                System.out.println("No: " + Sim.getNo());
                System.out.println("Company: " + Sim.getCompany());
                o2o_b_mobile Mobile = Sim.getMobile();
                System.out.println("Mobile IMEI: " + Mobile.getImei());
                System.out.println("Mobile Model: " + Mobile.getModel());
            }
            commit();
        } catch (Exception e) {
            rollback();
            System.out.println("Exception : " + e.getMessage() + "Cause : " + e.getCause());
        } finally {
            flush();
            close();
        }
    }

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

The output will be

Hibernate: select o2o_b_sim0_.SIM_NO as SIM1_9_, o2o_b_sim0_.SIM_COMPANY as SIM2_9_ from hba.SIM o2o_b_sim0_ where o2o_b_sim0_.SIM_NO=?
Hibernate: select o2o_b_mobi0_.MOB_IMEI as MOB1_8_1_, o2o_b_mobi0_.MOB_MODEL as MOB2_8_1_, o2o_b_mobi0_.MOB_SIM as MOB3_8_1_, o2o_b_sim1_.SIM_NO as SIM1_9_0_, o2o_b_sim1_.SIM_COMPANY as SIM2_9_0_ from hba.MOBILE o2o_b_mobi0_ left outer join hba.SIM o2o_b_sim1_ on o2o_b_mobi0_.MOB_SIM=o2o_b_sim1_.SIM_NO where o2o_b_mobi0_.MOB_SIM=?
List : [hba.pojo.o2o_b_sim@9a9b65]
No: 9496351113
Company: BSNL
Mobile IMEI: 123456789
Mobile Model: SAMSUNG CORBY

Thanks.