Hibernate Composite Key

In this tutorial I will show you how to map Composite Key in Hibernate.

First create a new Java Project and configure it as Maven Project. For Reference, Click Here

Add the following dependencies in pom.xml

<dependencies>
 
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
        <scope>test</scope>
    </dependency>
 
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.15</version>
    </dependency>
 
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.6.3.Final</version>
    </dependency>
 
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.6</version>
    </dependency>
</dependencies>

1. Sql Script

Use the following Sql Script for creating table.

create table PURCHASE_ORDERS (
    street varchar(255) not null,
    city varchar(255) not null,
    itemName varchar(255),
    primary key (street, city)
);

2. Pojo

Now create BillingAddress class. This class models the billing address for a person. The billing itself relates to another Java class called PurchaseOrder. Primary key of this table is combination of street and city. To map such classes we have to use <composite-key> tag. Both the street and city acts as identifier to the PURCHASE_ORDERS table.

package com.kruders.model.bean;

import java.io.Serializable;

public class BillingAddress implements Serializable {
	private String street;
    private String city;

    public BillingAddress() {}

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

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
    
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (!this.getClass().equals(obj.getClass())) return false;
        
        BillingAddress obj2 = (BillingAddress)obj;

        if (this.street.equals(obj2.getStreet()) &&
            this.city == obj2.getCity()) {
            return true;
        }
        return false;
    }

    public int hashCode() {      
        int tmp = 0;
        tmp = (street + city).hashCode();
        return tmp;
    }
}

Also create PurchaseOrder class and write the following code.

package com.kruders.model.bean;

public class PurchaseOrder {
	BillingAddress billingAddress;
	private String itemName;
	
	public String getItemName() {
		return itemName;
	}
	public BillingAddress getBillingAddress() {
		return billingAddress;
	}
	public void setBillingAddress(BillingAddress billingAddress) {
		this.billingAddress = billingAddress;
	}
	public void setItemName(String itemName) {
		this.itemName = itemName;
	}
	
}

3. Hibernate Mapping File

Now create HBM file PurchaseOrder.hbm.xml that maps classes to database tables.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.kruders.model.bean.PurchaseOrder" table="PURCHASE_ORDERS">
    <meta attribute="class-description">This class contains Purchase Order details.</meta>
    <composite-id name="billingAddress" >
		<key-property name="street" column="STREET" type="java.lang.String" />
		<key-property name="city" column="CITY" type="java.lang.String" />
	</composite-id>
    <property name="itemName" type="string" length="50" column="ITEMNAME" />
</class>
</hibernate-mapping>

4. Hibernate Configuration File

Now create the hibernate configuration file and add all the mapping files.
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.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password"></property>
		<property name="connection.pool_size">1</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="show_sql">true</property>
		<mapping resource="com/kruders/model/bean/PurchaseOrder.hbm.xml" />
	</session-factory>
</hibernate-configuration>

5. Hibernate Utility Class

Now create HibernateUtil class. The HibernateUtil class helps in creating the SessionFactory from the Hibernate configuration file. A org.hibernate.SessionFactory is used to obtain org.hibernate.Session instances. A org.hibernate.Session represents a single-threaded unit of work. The org.hibernate.SessionFactory is a thread-safe global object that is instantiated once.

package com.kruders.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
  
public class HibernateUtil {
  
    private static final SessionFactory sessionFactory = buildSessionFactory();
  
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
  
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

6. Run Program

Create Main.java class that inserts a record and run it as Java Application

package com.kruders.core;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.kruders.model.bean.BillingAddress;
import com.kruders.model.bean.PurchaseOrder;
import com.kruders.util.HibernateUtil;

public class Main {
	public static void main(String args[]) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
        try {
             
            transaction = session.beginTransaction();
            BillingAddress billingAddress = new BillingAddress();
            billingAddress.setCity("Delhi");
            billingAddress.setStreet("G.T. Karnal Road");
            
            PurchaseOrder purchaseOrder = new PurchaseOrder();
            purchaseOrder.setItemName("Fruits");
            purchaseOrder.setBillingAddress(billingAddress);
            session.save(purchaseOrder);
            transaction.commit();
        }catch (HibernateException e) {
            transaction.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }
}

The folder structure of the example is shown below in Figure 22.1

Figure 22.1 Figure 22.1

You can download the source code of this example here.

No comments yet.

Leave a Reply