Monday, August 8, 2011

HIBERNATE - Bi-directional One-to-One Association

In the following example, we will be going through the Bidirectional 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. The one-to-one association is achieved using the many-to-one concept in hibernate that is explained in the below section.

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 ADDRESS_O;
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
);

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 terminology OTO_B to indicate that its a one-to-one bi-directional association.

PersonOTO_B.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="PersonOTO_B" 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>

PersonAddressOTO_B.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="PersonAddressOTO_B" 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" />

        <!-- In One-to-one we cannot specify the foreign key column 
             that has to be filled up
            <one-to-one name="person" class="PersonOTO_B" cascade="all"
            constrained="true"> </one-to-one>
        -->

        <many-to-one name="person" column="P_ID" unique="true"
            not-null="true" lazy="false" />
    </class>
</hibernate-mapping>

Java Files:

PersonOTO_B.java:

package org.mybusiness.pojos;

import java.io.Serializable;

public class PersonOTO_B implements Serializable {

    private static final long serialVersionUID = -9127358545321739524L;

    private int id;
    private String name;
    private int age;
    private PersonAddressOTO_B 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 PersonAddressOTO_B getAddress() {
        return address;
    }

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

PersonAddressOTO_B.java:

package org.mybusiness.pojos;

import java.io.Serializable;

public class PersonAddressOTO_B implements Serializable {

    private static final long serialVersionUID = -9127358545321739523L;

    private int id;
    private String addressLine1;
    private String city;
    private String state;
    private int zipCode;
    private PersonOTO_B person;

    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 PersonOTO_B getPerson() {
        return person;
    }

    public void setPerson(PersonOTO_B person) {
        this.person = person;
    }
}

Functionalities:

AddPerson:

public void addPersonOTO_B() {

    HibernateTemplate ht = new HibernateTemplate(sessionFactory);

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

    try {

        // Create a person
        PersonOTO_B person = new PersonOTO_B();
        person.setName("Luna");
        person.setAge(33);

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

        // Create the address for the person
        PersonAddressOTO_B address = new PersonAddressOTO_B();
        address.setAddressLine1("Lunaris");
        address.setCity("Twinkle");
        address.setState("MA");
        address.setZipCode(10308);
        address.setPerson(person);

        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();
    }
}

Retrieve Address & Persons:

public void getAddress() {

    HibernateTemplate ht = new HibernateTemplate(sessionFactory);

    PersonAddressOTO_B address = (PersonAddressOTO_B) ht.get(
            PersonAddressOTO_B.class, 1);

    printAddress(address);

    PersonOTO_B person = (PersonOTO_B) ht.get(PersonOTO_B.class, address
            .getPerson().getId());

    printPerson(person);
}

public void getAddressWithRestrictions() {

    HibernateTemplate ht = new HibernateTemplate(sessionFactory);

    DetachedCriteria criteria = DetachedCriteria.forClass(
            PersonAddressOTO_B.class, "a");
    criteria.createAlias("person", "p");
    criteria.add(Restrictions.ilike("p.name", "L", MatchMode.START));
    criteria.add(Restrictions.eq("a.zipCode", 50102));

    List<PersonAddressOTO_B> address = ht.findByCriteria(criteria);
    printAddress(address);
}

private void printAddress(List<PersonAddressOTO_B> address) {

    for (PersonAddressOTO_B add : address) {
        printAddress(add);
    }
}

private void printAddress(PersonAddressOTO_B address) {

    System.out.println("-----------------------------------");
    System.out.println(address.getId());
    System.out.println(address.getAddressLine1());
    System.out.println(address.getCity() + "," + address.getState() + ","
            + address.getZipCode());
    System.out.println(address.getPerson().getId() + ","
            + address.getPerson().getName() + ","
            + address.getPerson().getAge());
}

private void printPerson(PersonOTO_B person) {

    System.out.println("-----------------------------------");
    System.out.println(person.getId() + "," + person.getName() + ","
            + person.getAge());
    System.out.println(person.getAddress().getId() + ","
            + person.getAddress().getAddressLine1() + ","
            + person.getAddress().getCity() + ","
            + person.getAddress().getState() + ","
            + person.getAddress().getZipCode());
}

No comments:

Post a Comment