Friday, August 5, 2011

HIBERNATE - Unidirectional One-to-One Association

In the following example, we will be going through the Unidirectional One-to-One association using Hibernate. We will be using the Person and Address table where one person will have only one address and an address can belong to only one person.

Schema Creation:

We will be creating two tables Person and Address. Each Person will have an Address associated with him/her and the one-to-one relationship is maintained using the UNIQUE constraint on the foreign key column on the Address table.

DROP TABLE PERSONS_O;
CREATE TABLE PERSONS_O (
 P_ID INTEGER(5) PRIMARY KEY DEFAULT 1,
 NAME VARCHAR(30) NOT NULL,
 AGE INTEGER(2) NOT NULL
);

DROP TABLE ADDRESS_O;
CREATE TABLE ADDRESS_O (
 A_ID INTEGER(5) PRIMARY KEY DEFAULT 1,
 ADDRESS_LINE_1 VARCHAR(30) NOT NULL,
 CITY VARCHAR(20)NOT NULL,
 STATE VARCHAR(2)NOT NULL,
 ZIPCODE INTEGER(5)NOT NULL,
 P_ID INTEGER(5) UNIQUE,
 FOREIGN KEY(P_ID) REFERENCES PERSONS_O(P_ID)
);

HBM Files Creation:

I used the as xxxO to indicate that its a one-to-one association.

PersonO.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.mybusiness.pojos">
    <class name="PersonO" table="persons_o">
        <id name="id" column="P_ID" type="integer">
            <generator class="increment" />
        </id>

        <property name="name" column="NAME" update="false"
            type="string" />

        <property name="age" column="AGE" type="integer" />

        <one-to-one name="address" cascade="all"></one-to-one>
    </class>
</hibernate-mapping>

PersonAddressO.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.mybusiness.pojos">
    <class name="PersonAddressO" table="address_o" dynamic-insert="true"
        dynamic-update="true" select-before-update="false">
        <id name="id" column="A_ID" type="integer">
            <generator class="increment" />
        </id>

        <property name="addressLine1" column="ADDRESS_LINE_1"
            type="string" />

        <property name="city" column="CITY" type="string" />

        <property name="state" column="STATE" type="string" />

        <property name="zipCode" column="ZIPCODE" type="integer" />

        <property name="personId" column="P_ID" type="integer" />
    </class>
</hibernate-mapping>

Java Files:

PersonO.java:

package org.mybusiness.pojos;

import java.io.Serializable;

public class PersonO implements Serializable {

    private static final long serialVersionUID = -9127358545321739524L;

    private int id;
    private String name;
    private int age;
    private PersonAddressO address;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public PersonAddressO getAddress() {
        return address;
    }

    public void setAddress(PersonAddressO address) {
        this.address = address;
    }
}

PersonAddressO.java:

package org.mybusiness.pojos;

import java.io.Serializable;

public class PersonAddressO implements Serializable {

    private static final long serialVersionUID = -9127358545321739523L;

    private int id;
    private String addressLine1;
    private String city;
    private String state;
    private int zipCode;
    private int personId;

    public int getId() {
        return id;
    }

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

    public String getAddressLine1() {
        return addressLine1;
    }

    public void setAddressLine1(String addressLine1) {
        this.addressLine1 = addressLine1;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public int getZipCode() {
        return zipCode;
    }

    public void setZipCode(int zipCode) {
        this.zipCode = zipCode;
    }

    public int getPersonId() {
        return personId;
    }

    public void setPersonId(int personId) {
        this.personId = personId;
    }
}

Functionalities:

AddPerson:

public void addPerson() {

    HibernateTemplate ht = new HibernateTemplate(sessionFactory);

    Session s = ht.getSessionFactory().openSession();
    Transaction tx = s.beginTransaction();

    try {

        // Create a person
        PersonO person = new PersonO();
        person.setName("Luke");
        person.setAge(18);

        Integer key = (Integer) s.save(person);
        System.out.println("Primary Key : " + key);

        // Create the address for the person
        PersonAddressO address = new PersonAddressO();
        address.setAddressLine1("Shines");
        address.setCity("Caramel");
        address.setState("UT");
        address.setZipCode(80708);
        address.setPersonId(key);

        person.setAddress(address);

        key = (Integer) s.save(address);
        System.out.println("Primary Key again : " + key);
        tx.commit();
    } catch (Exception e) {
        e.printStackTrace();
        tx.rollback();
    } finally {
        s.close();
    }
}

RetrievePersons:

public void retrieveAllPersons() {

    HibernateTemplate ht = new HibernateTemplate(sessionFactory);

    DetachedCriteria criteria = DetachedCriteria.forClass(PersonO.class,
            "person");

    List<PersonO> persons = ht.findByCriteria(criteria);
    printPerson(persons);
}

private void printPerson(List<PersonO> persons) {
    for (PersonO p : persons) {
        System.out
                .println("---------------------------------------------------");
        System.out
                .println(p.getId() + "," + p.getName() + "," + p.getAge());
        System.out.println(p.getAddress().getAddressLine1() + ","
                + p.getAddress().getCity() + ","
                + p.getAddress().getState() + ","
                + p.getAddress().getZipCode());
        System.out
                .println("---------------------------------------------------");
    }
}

Retrieve Using Restrictions:

public void retrievePersonsWithRestrictions() {

    HibernateTemplate ht = new HibernateTemplate(sessionFactory);

    DetachedCriteria criteria = DetachedCriteria.forClass(PersonO.class,
            "p");
    criteria.createAlias("address", "a");
    criteria.add(Restrictions.eq("p.age", 26));
    criteria.add(Restrictions.ilike("a.state", "M", MatchMode.ANYWHERE));
    criteria.add(Restrictions.sqlRestriction("ZIPCODE > 50000"));
    criteria.addOrder(Order.desc("p.name"));
    criteria.addOrder(Order.asc("a.zipCode"));

    List<PersonO> persons = ht.findByCriteria(criteria);
    printPerson(persons);
}

1 comment:

  1. Wonderful. Thanks a lot.

    Will my http://stackoverflow.com/questions/17614439/circular-dependecy-of-pojo-in-hibernate-project get solved with this approach.

    ReplyDelete