Hibernate Component Mapping - Walking Techie

Blog about Java programming, Design Pattern, and Data Structure.

Wednesday, June 3, 2020

Hibernate Component Mapping

A component is a part of whole in such a way that if component is destroyed, all its parts are also destroyed with it.

For example, Here the house has its rooms as part and the house itself as a whole. When the house is destroyed its rooms are also destroyed. Each part (component) belongs to only one whole. It means it is not shared with others just like a room in a house. Room is the part of your house, not your neighbors.

Composition relationship

The term "component" refers to the object-oriented notion of composition. It is a embedded object that is persisted as a value type. So its existence depend only on the entity type that contains it. Because component does not have its own identity in database.

Let's take one example of Person and Address object model. Here Address is a component (HAS-A relation) of Person.

Person and Address mapping

Address class is a component of Person class. In this situation, You will have more classes than the number of corresponding database's tables to store data of them.

component mapping into a table

In this example, we have two classes Person and Address, but have only one table person to store data of them. So we are mapping to classes to one table.

package com.walking.techie.entity;

import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class Person {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @Column(nullable = false)
  private String name;

  @Embedded
  private Address address;

  public Person() {
  }

  public Person(String name, Address address) {
    this.name = name;
    this.address = address;
  }
}

Person class is an entity class and it has address member variable. To make address attribute as a component of Person class. We mark it with @Embedded annotation.

package com.walking.techie.entity;

import javax.persistence.Embeddable;

@Embeddable
public class Address {

  private String street;
  private String city;
  private String zipcode;

  public Address() {
  }

  public Address(String street, String city, String zipcode) {
    this.street = street;
    this.city = city;
    this.zipcode = zipcode;
  }
}

Here, Address class is a component, that is a dependent object. We have mark it with @Embeddable annotation to make it a persistent class.

Data of both the class will save into one table like below.

Table record

Hibernate Properties

hibernate.cfg.xml is a Hibernate configuration xml file which contain the required Hibernate properties. Most of the properties have their default properties. Some of the properties values need to have into this file, so Hibernate use these properties to create connection with database.

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

<hibernate-configuration>
  <session-factory>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/helloworld?useSSL=false</property>
    <property name="connection.username">root</property>
    <property name="connection.password">santosh</property>
    <property name="hbm2ddl.auto">create-drop</property>

    <!-- SQL Dialect -->
    <property name="dialect">org.hibernate.dialect.MariaDBDialect</property>
    <!--Echo all executed SQL query to console-->
    <property name="show_sql">true</property>
    <mapping class="com.walking.techie.entity.Person"/>
  </session-factory>
</hibernate-configuration>

ComponentMappingClient

This class main method will save the person object into Person table of helloworld database.

package com.walking.techie;

import com.walking.techie.entity.Address;
import com.walking.techie.entity.Person;
import com.walking.techie.utils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class ComponentMappingClient {

  public static void main(String[] args) {
    // get session factory of an application
    SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

    // Open a session
    Session session = sessionFactory.openSession();
    Transaction transaction = null;

    try {
      // Begin a unit of work and return the associated Transaction object.
      transaction = session.beginTransaction();

      Address address = new Address("6th cross, 6th main", "Bangalore", "560078");
      Person person = new Person("Santosh", address);

      session.persist(person);

      // commit the transaction
      transaction.commit();
    } catch (Exception e) {
      if (transaction != null) {
        transaction.rollback();
        e.printStackTrace();
      }
    } finally {
      if (session != null) {
        // End the session by releasing the JDBC connection and cleaning up.
        session.close();
      }
    }
  }
}

Before running this application you need to create the helloworld database into MySQL. Table will created automatically because we have set the hbm2ddl.auto to create-drop.

Output

This application will save the person object and its component address object in Person table.

output in console

Hibernate: create table Person (id bigint not null auto_increment, city varchar(255), street varchar(255), zipcode varchar(255), name varchar(255) not null, primary key (id)) engine=InnoDB
Jun 03, 2020 4:49:03 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@1e0f9063] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Jun 03, 2020 4:49:04 PM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@63a270c9'
Hibernate: insert into Person (city, street, zipcode, name) values (?, ?, ?, ?)

You can find the working code of above example on github.

1 comment :