12 - Component Mapping in Hibernate

12.1 Overview

Java supports composition in the form of has-a relationship. Composition is stronger association where the contained object has no existence of its own. For example Person has an address, Person has a job . In these examples job and address have no existence without Person.

We  may want to store contained objects like Job, Address etc in the same entity table (person) as a value type and Hibernate does support this feature using <component> tag.

Most important thing is – contained object is not stored in a separate table instead it will be stored as a value type in table corresponding to contained object and we can have nested component mapping.

12.2 Attributes of <component> element.

There are several attributes supported by component element. Below are the details of most commonly used attributes.

  1. access – is used to specify the property access strategy. Properties can be accessed using “field” (no need of get/set) or a property (using get/set) . Possible values are filed and property.
  2. class- qualified class name of the component.
  3. name- name of the attribute of the parent class corresponding to this component.
  4. update- possible values are true and false and can be used to control the updates of the component through parent object. If update is set to false then any updates in the component will not be reflected in database.
  5. insert- possible values are true and false and can be used to control the insert of the component through parent object. If insert is set to false then component values will not be inserted along with parent object.

12.3 Example

“Person has a job” can be the example of Composition in java as job has no existence of its own.

Person.java

package com.tutorial.hibernate;

public  class Person {

    private int id;
    private String name;
    private Job job;
    private String emailAddress;

    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 Job getJob() {
        return job;
    }
    public void setJob(Job job) {
        this.job = job;
    }
    public String getEmailAddress() {
        return emailAddress;
    }
    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", job=" + job
                + ", emailAddress=" + emailAddress + "]";
    }

}

Job.java

package com.tutorial.hibernate;

    public class Job {
       private String designation;
       private int salary;
       private String  jobDescription;
  
         public String getDesignation() {
           return designation;
         }
 
         public void setDesignation(String designation) {
          this.designation = designation;
         }

         public int getSalary() {
          return salary;
         }

         public void setSalary(int salary) {
          this.salary = salary;
         }

         public String getJobDescription() {
           return jobDescription;
         }

         public void setJobDescription(String jobDescription) {
           this.jobDescription = jobDescription;
         }
} 

Create PERSON Table

   create table PERSON (
        person_id integer not null auto_increment,
        name varchar(255),
        email_address varchar(255),
        designation varchar(255),
        salary integer,
        job_description varchar(255),
        primary key (person_id)
    )

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
  
     <session-factory>

         <property name="hibernate.connection.url">
              jdbc:mysql://localhost:3306/tutorial
         </property>
         <property name="hibernate.connection.username">
             root
         </property>
         <property name="hibernate.connection.password">
             password
         </property>
         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

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

         <mapping resource="component-mapping.hbm.xml" />
    </session-factory>
</hibernate-configuration>

Test program

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import com.tutorial.hibernate.Job;
import com.tutorial.hibernate.Person;

public class Test {

     public static void main(String args[])
     {
        Configuration cfg = new Configuration().configure();        
        SessionFactory factory = cfg.buildSessionFactory();
        Session session=  factory.openSession();

        Transaction tx = session.beginTransaction();

        Job job = new Job();
        job.setDesignation("Project Manager ");
        job.setSalary(4500);
        job.setJobDescription("Manages Team and Deliveries");

        Person person = new Person();
        person.setEmailAddress("person@company.com");
        person.setJob(job);
        person.setName("Person A");

        session.save(person);

        tx.commit();
        session.close();

        session=  factory.openSession();

        Person p= (Person)session.get(Person.class, person.getId());
        System.out.println(p);

        session.close();
        factory.close();
    }
}

Run Test program

If you add Person reference in Job class and call job.getPerson() it will return null because we have defined unidirectional relationship from Person to Job.

12.3.1 Bidirectional Component Mapping-

To define a bi-directional relationship, we need to add update the mapping as below (add parent tag). Name attribute will be the property name .With this we can get Person object from Job as well.

<?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>
   <class name="com.tutorial.hibernate.Person" table="PERSON">
      <id name="id" type="int" column="person_id">
         <generator class="native"/>
      </id>
     <property name="name" column="name" type="string"/>
     <property name="emailAddress" column="email_address" type="string"/>

     <component name="job" class="com.tutorial.hibernate.Job" >
        <parent name="person" />
        <property name="designation" column="designation" type="string"/>
        <property name="salary" column="salary" type="int"/>
        <property name="jobDescription" column="job_description" type="string"/>     
     </component> 
   </class>
</hibernate-mapping> 

12.3.2 Update scenario of section 12.3 to control insert and update of component.

We can control the insert and update of component using insert and update attributes.

Update component-mapping.hbm.xml file as follows 

<?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>
   <class name="com.tutorial.hibernate.Person" table="PERSON">
      <id name="id" type="int" column="person_id">
         <generator class="native"/>
      </id>
     <property name="name" column="name" type="string"/>
     <property name="emailAddress" column="email_address" type="string"/>

    <component name="job" class="com.tutorial.hibernate.Job" update="false" insert="false">
        <parent name="person" />
        <property name="designation" column="designation" type="string"/>
        <property name="salary" column="salary" type="int"/>
        <property name="jobDescription" column="job_description" type="string"/>     
     </component> 

   </class>
</hibernate-mapping>

Run Test Program – This time Job details will not be inserted.

Like us on Facebook