Saturday, November 12, 2011

Java Hibernate Multiple Map into One Table

Hi Friends,

Recently I was trying to do something different. I could not find exact solution what I was looking for. Thus sharing here. Some one else might be benefited by this.

Now I will get straight to the point. First the problem statement:

I have a Java class like this


import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

/**
 * @author: Aniruddha Dutta Chowdhury

 *
 */
public class HibernateDemo implements Serializable {
    private static Logger        logger            = Logger.getLogger(HibernateDemo.class);

    private Map    requestData        = new HashMap();
    private Map    contextData        = new HashMap();
    private Map    responsetData    = new HashMap();
    private Date                timeOfAction    = null;
    private Long                id                = null;
   
    public Map getResponsetData() {
        return responsetData;
    }
   
    public void setResponsetData(Map responsetData) {
        this.responsetData = responsetData;
    }

    public Long getId() {
        return id;
    }

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

    public Date getTimeOfAction() {
        return timeOfAction;
    }

    public void setTimeOfAction(Date timeOfAction) {
        this.timeOfAction = timeOfAction;
    }

    public Map getRequestData() {
        return requestData;
    }

    public void setRequestData(Map requestData) {
        this.requestData = requestData;
    }

    public Map getContextData() {
        return contextData;
    }

    public void setContextData(Map contextData) {
        this.contextData = contextData;
    }

    public Map getResponseData() {
        return responseData;
    }

    public void setResponseData(Map responseData) {
        this.responseData = responseData;
    }

    private Map    responseData    = new HashMap();
}


And I wanted only two tables for this whole class. One for the main class and another one for all the map members.

Desired tables are as follows:


MAIN_TABLE
ID PK
ACTION_TIME


AND the child table would be


CHILD_TABLE
PARENT_ID FK
KEY
VALUE
DISCRIMINATOR

Now this is not a big deal for hibernate. Using the where clause. But the question comes that how to fill the value for discriminator. Then after going through hibernate api I came up with this. The SQL-INSERT is really very handy in this case.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
    <class name="HibernateDemo" table="MAIN_TABLE">
        <id name="id">
            <generator class="native" />
        </id>
        <property name="timeOfAction" />
        <map name="requestData" table="CHILD_TABLE" where="DISCRIMENATOR='REQUEST'">       
            <key column="PARENT_ID" />
            <index column="KEY" type="string" />
            <element column="VALUE" type="string" />
            <sql-insert>insert into CHILD_TABLE (PARENT_ID, KEY, VALUE, DISCRIMENATOR) values (?, ?, ?, 'REQUEST')</sql-insert>
        </map>
       
        <map name="contextData" table="CHILD_TABLE" where="DISCRIMENATOR='CONTEXT'">       
            <key column="PARENT_ID" />
            <index column="KEY" type="string" />
            <element column="VALUE" type="string" />
            <sql-insert>insert into CHILD_TABLE (PARENT_ID, KEY, VALUE, DISCRIMENATOR) values (?, ?, ?, 'CONTEXT')</sql-insert>
        </map>
       
        <map name="responsetData" table="CHILD_TABLE" where="DISCRIMENATOR='RESPONSE'">       
            <key column="PARENT_ID" />
            <index column="KEY" type="string" />
            <element column="VALUE" type="string" />
            <sql-insert>insert into CHILD_TABLE (PARENT_ID, KEY, VALUE, DISCRIMENATOR) values (?, ?, ?, 'RESPONSE')</sql-insert>
        </map>
    </class>
</hibernate-mapping>



Hope this will help you. Till next time, BYE.

9 comments: