Powered By Blogger
Showing posts with label hibernate. Show all posts
Showing posts with label hibernate. Show all posts

Tuesday, December 3, 2013

Hibernate Composite Key Mapping (JPA)

   It is sometimes necessary to have composite keys in a database table. In such a scenario, it would be necessary to get hibernate to cater this requirement. This is an illustration of how it could be done.
   Consider an entity, BankFacilityAgent which has percentage and isKeyFacilitator as attributes and another attribute, key of type BankFacilityAgentKey. The class is annotated with @Table and @Entity. The class is bound to a database table, BANK_FAC_AGENT. Getters of attributes percentage and isKeyFacilitator are annotated with @javax.persistence.Column and @Basic. Note that getter of 'key' attribute is annotated with @Id.

===============================================================

package com.shyarmal.persistance.domain;

import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "BANK_FAC_AGENT", catalog = "")
@Entity
public class BankFacilityAgent {

    private BankFacilityAgentKey key;
    private float percentage;
    private String isKeyFacilitator;

    @Id
    public BankFacilityAgentKey getKey() {
        return key;
    }

    public void setKey(BankFacilityAgentKey key) {
        this.key = key;
    }

    @javax.persistence.Column(name = "PERCENTAGE")
    @Basic
    public float getPercentage() {
        return percentage;
    }

    public void setPercentage(float percentage) {
        this.percentage = percentage;
    }

    @javax.persistence.Column(name = "KEY_FACILITATOR")
    @Basic
    public String getKeyFacilitator() {
        return isKeyFacilitator;
    }

    public void setKeyFacilitator(String keyFacilitator) {
        isKeyFacilitator = keyFacilitator;
    }
}


===============================================================


   BankFacilityAgentKey represents the composite key, which should implement Serializable and is annotated with @Embeddable. This class holds attributes that comprise the composite key (bankId, facilityAgentId). The getters of the attributes are annotated the same way as in the class above.

===============================================================

package com.shyarmal.persistance.domain;

import javax.persistence.Basic;
import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
public class BankFacilityAgentKey implements Serializable {

    private int bankId;
    private int facilityAgentId;

    public BankFacilityAgentKey(int bankId, int facilityAgentId) {
        this.bankId = bankId;
        this.facilityAgentId = facilityAgentId;
    }

    public BankFacilityAgentKey() {

    }

    @javax.persistence.Column(name = "BANK_ID")
    @Basic
    public int getBankId() {
        return bankId;
    }

    public void setBankId(int bankId) {
        this.bankId = bankId;
    }

    @javax.persistence.Column(name = "FACILITY_AGENT_ID")
    @Basic
    public int getFacilityAgentId() {
        return facilityAgentId;
    }

    public void setFacilityAgentId(int facilityAgentId) {
        this.facilityAgentId = facilityAgentId;
    }
}

===============================================================

   The database table mapped is BANK_FAC_AGENT with columns PERCENTAGE, KEY_FACILITATOR, BANK_ID and FACILITY_AGENT_ID where BANK_ID and FACILITY_AGENT_ID are the composite key.


thanks,
Shyarmal.

Sunday, August 19, 2012

Hibernate enum mapping - hmb

The following example shows how to map enums using hbm files. Media is the enum which is mapped in this means. It has a 'description' attribute which will be saved in the database. The methods 'getDescription()' and 'getMedia(String)' are used to retrieve the description and the media of 'Media' respectively. Notice the latter is static and returns corresponding enum type of the value passed into it.

==============================================================
package com.shyarmal.hibernate.example.model;

public enum Media {

    PRINTED("PRINTED"), ELECTRONIC("ELECTRONIC"), UNKNOWN("UNKNOWN");
    private String description;

    Media(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    public static Media getMedia(String value) {
        if ("PRINTED".equals(value)) {
           return PRINTED;
        } else if ("ELECTRONIC".equals(value)) {
           return ELECTRONIC;
        } else {
            return UNKNOWN;
        }
    }
}
==============================================================

A custom enum user type is defined below, implementing the interfaces UserType and ParameterizedType. Parameters of the typedef element of the hbm (found below) are used in 'setParameterValues(Properties)' to initialize the enum type and it's methods. The methods  nullSafeGet(ResultSet rs, String[] names, Object owner)and nullSafeGet(ResultSet rs, String[] names, Object owner) are used to get and set the enum from and to the database.

==============================================================

package com.shyarmal.hibernate.example.model;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.type.NullableType;
import org.hibernate.type.TypeFactory;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class EnumUserType implements UserType, ParameterizedType {

    private static final String IDENTIFIER_METHOD = "name";
    private static final String VALUE_OF_METHOD = "valueOf";
    private Class<? extends Enum> enumClass;
    private Class<?> identifierType;
    private Method identifierMethod;
    private Method valueOfMethod;
    private NullableType type;
    private int[] sqlTypes;

    public void setParameterValues(Properties parameters) {
        String enumClassName = parameters.getProperty("enumClass");
        try {
            enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
        } catch (ClassNotFoundException cfne) {
            throw new HibernateException("Enum class not found", cfne);
        }

        String identifierMethodName = parameters.getProperty("identifierMethod", IDENTIFIER_METHOD);
        try {
            identifierMethod = enumClass.getMethod(identifierMethodName, new Class[0]);
            identifierType = identifierMethod.getReturnType();
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain identifier method", e);
        }

        type = (NullableType) TypeFactory.basic(identifierType.getName());
        if (type == null)
            throw new HibernateException("Unsupported identifier type " + identifierType.getName());
        sqlTypes = new int[]{Hibernate.STRING.sqlType()};
        String valueOfMethodName = parameters.getProperty("valueOfMethod", VALUE_OF_METHOD);
        try {
            valueOfMethod = enumClass.getMethod(valueOfMethodName, new Class[]{identifierType});
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain valueOf method", e);
        }
    }

    public Class returnedClass() {
        return enumClass;
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        Object identifier = type.get(rs, names[0]);
        if (rs.wasNull()) {
            return null;
        }

        try {
            return valueOfMethod.invoke(enumClass, new Object[]{identifier});
        } catch (Exception e) {
            throw new HibernateException("Error in valueOf method '" + valueOfMethod.getName()
                    + "' of " + "enum class '" + enumClass + "'", e);
        }
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        try {
            if (value == null) {
                st.setNull(index, type.sqlType());
            } else {
                Object identifier = identifierMethod.invoke(value, new Object[0]);
                type.set(st, identifier, index);
            }
        } catch (Exception e) {
            throw new HibernateException("Error in identifierMethod '" + identifierMethod.getName()
                    + "' of " + "enum class '" + enumClass + "'", e);
        }
    }

    public int[] sqlTypes() {
        return sqlTypes;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return x == y;
    }

    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    public boolean isMutable() {
        return false;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
}

==============================================================

I have posted the hbm file below. Only the configurations relevant to the type mapping is present. A type should be defined first, which is done with the 'typedef' element. So a type, 'media' is defined providing the class above, EnumUserType. Parameters 'enumClass', 'identifierMethod' and 'valueOfMethod' are defined. The parameter 'enumClass' is our enum, Media. Other two parameters, identifierMethod and valueOfMethod are the methods getDescription() and getMedia(String) respectively.

==============================================================

<?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="com.shyarmal.hibernate.example.model">

    <typedef name="media" class="com.shyarmal.hibernate.example.model.EnumUserType">
        <param name="enumClass">com.shyarmal.hibernate.example.model.Media</param>
        <param name="identifierMethod">getDescription</param>
        <param name="valueOfMethod">getMedia</param>
    </typedef>

    <class name="Xxxxx" table="XXXX_XXX">
        <!--
            ---- Other property definitions. ----
        -->           
        <property name="media" column="MEDIA" type="media"/>
    </class>

</hibernate-mapping>

==============================================================

After defining a type as described above, a property should be defined for the class (here it's Xxxxx), which should have an attribute called media of type 'Media' (our enum). So '<property name="media" column="MEDIA" type="media"/>' says that the property 'media' of the class Xxxxx of type 'media' (our defined type using typedef) will be mapped to 'MEDIA' column of 'XXXX_XXX' table in the database.


reference: using-enum-hibernate

thanks,
Shyarmal.

Sunday, August 12, 2012

Hibernate Hierarchy Mapping - Table Per Class

This example shows how to map a hierarchy with hibernate using the strategy, table per class. Circle and Square are two classes which extend Shape. The attribute, id of Shape is common to both the subclasses and will be the primary key of the tables created.

===================================================================
// The shape class
package com.shyarmal.hibernate.example.shape;

public class Shape implements IPersistable {

    protected long id;

    public long getId() {
        return id;
    }

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


// Subclass of Shape, Circle
package com.shyarmal.hibernate.example.shape;

public class Circle extends Shape {

    private float radius;
    private float centerX;
    private float centerY;

    public float getRadius() {
        return radius;
    }

    public void setRadius(float radius) {
        this.radius = radius;
    }

    public float getCenterX() {
        return centerX;
    }

    public void setCenterX(float centerX) {
        this.centerX = centerX;
    }

    public float getCenterY() {
        return centerY;
    }

    public void setCenterY(float centerY) {
        this.centerY = centerY;
    }
}


// Subclass of Shape, Square
package com.shyarmal.hibernate.example.shape;

public class Square extends Shape {

    private float length;
    private float topX;
    private float topY;

    public float getTopX() {
        return topX;
    }

    public void setTopX(float topX) {
        this.topX = topX;
    }

    public float getlength() {
        return length;
    }

    public void setlength(float length) {
        this.length = length;
    }

    public float getTopY() {
        return topY;
    }
    public void setTopY(float topY) {
        this.topY = topY;
    }
}

===================================================================
The hibernate xml mapping for the above hierarchy is as follows. All three classes mapping configurations are done in the same hmb file. This configuration will map (and/or create) three tables for the three classes.

===================================================================
<?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="com.shyarmal.hibernate.example.shape">
    <class name="Shape" table="SHAPE">
        <id name="id" column="ID" type="long">
            <generator class="native" />
        </id>
        <joined-subclass table="CIRCLE" name="Circle">
            <key column="ID" />
            <property name="radius" column="RADIUS" type="float"/>
            <property name="centerX" column="CENTER_X" type="float"/>
            <property name="centerY" column="CENTER_Y" type="float"/>
        </joined-subclass>
        <joined-subclass table="SQUARE" name="Square">
            <key column="ID" />       
            <property name="length" type="float" column="LENGTH"/>
            <property name="topY" column="TOP_Y" type="float" />
            <property name="topX" column="TOP_X" type="float" />
        </joined-subclass>
    </class>
</hibernate-mapping>

===================================================================

As you can notice, the 'class' tag refers to the class, Shape and the primary key is it's id attribute  (mapped with 'generator' tag). Subclasses are mapped with the element, 'joined-subclass', enclosed in 'class' tag. The element, 'key' defines a (foreign key) reference to the 'ID' column of the 'SHAPE' table. Further, the properties specific to each subclass is defined within the 'joined-subclass' element.

thanks,
Shyarmal.

Wednesday, December 28, 2011

Open Session In View Filter Usage

Open Session In View Filter of Spring framework takes care of hibernate session management of a web application.  The integration of it is done at the web.xml.

Firstly, the spring beans ought to be loaded to the application context. This is done with a 'context-param' element. Secondly, define a filter with a 'filter' element (here my filter class is com.shyarmal.filter.MyOpenSessionInViewFilter which extends org.springframework.orm.hibernate3.support.OpenSessionInViewFilter).  Thirdly, define a filter mapping to the filter appropriately using 'filter-mapping' element. Notice the init parameter (sessionFactoryBeanName) passed to the filter. It is the id of the session factory defined in spring beans xml configurations.

web.xml elements of interest are as follows.
===================================================================
<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>/WEB-INF/springmvc-servlet.xml</param-value>
</context-param>

<filter>
   <filter-name>openSessionInViewFilter</filter-name>
   <filter-class>com.shyarmal.filter.MyOpenSessionInViewFilter</filter-class>
   <init-param>
        <param-name>sessionFactoryBeanName</param-name>
        <param-value>sessionFactory</param-value>
   </init-param>
</filter>

<filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>
===================================================================

Following are the spring bean definitions related to session factory used for the integration of open session in view filter.
===================================================================

<bean id="hibernateConfigProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
   <property name="location">
       <value>classpath:hibernate.properties</value>
   </property>
</bean>

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="${jdbc.driver.class.name}"/>
   <property name="url" value="${jdbc.url}"/>
   <property name="username" value="${jdbc.username}"/>
   <property name="password" value="${jdbc.password}"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>Accounts.hbm.xml</value>
             .....
            .....
            .....
        </list>
    </property>
    <property name="hibernateProperties" ref="hibernateConfigProperties"/>
</bean>

===================================================================

thanks,
Shyarmal.

Sunday, December 11, 2011

Detached Criteria - Hibernate

The following is an example usage of DetachedCriteria in hibernate. CoinTrxLedger is the domain class which is to be queried and it consists of a set of CoinBuckets. Detached Criteria is used to prepare a sub-query using CoinBuckets (which is not the main query class).
CoinTrxLedger entities are to be selected, which are having CoinBucket entities having the CoinBucket.PROPERTY_ACCOUNT set to An entity, account (passed in to the method).

===================================================================

    public List<CoinTrxLedger> getTransactionEntries(Account account) {
        Session session = getSessionFactory().getCurrentSession();
        Criteria criteria = session.createCriteria(CoinTrxLedger.class);
        DetachedCriteria dCriteria = DetachedCriteria.forClass(CoinBucket.class);
        dCriteria.add(Restrictions.eq(CoinBucket.PROPERTY_ACCOUNT, account));
        dCriteria.setProjection(Projections.property(CoinBucket.PROPERTY_ID));
        criteria.add(Subqueries.propertyEq(CoinTrxLedger.PROPERTY_COIN_BUCKET, dCriteria));
        return criteria.list();
    }

===================================================================

Create a criteria of the query entity;
          Criteria criteria = session.createCriteria(CoinTrxLedger.class);

Create the sub-query, define restrictions and projections as required:
         DetachedCriteria dCriteria = DetachedCriteria.forClass(CoinBucket.class);
     dCriteria.add(

Restrictions.eq(CoinBucket.PROPERTY_ACCOUNT, account));
     dCriteria.setProjection(Projections

.property(CoinBucket.PROPERTY_ID));

Add the sub-query to the main criteria:
        criteria.add(
Subqueries.propertyEq(CoinTrxLedger.PROPERTY_COIN_BUCKET, dCriteria));

thanks,
Shyarmal

Saturday, September 17, 2011

Hibernate with JPA Annotations - OneToOne

 This example illustrates a one-to-one mapping in Hibernate using JPA annotations. The illustration is about a case where a driver has one driving license. Here the license details will be saved to a database table by the name 'license' and that of driver to 'driver'. I'm only discussing the OneToOne mapping here. [For other basic information, refer to Hinernate Annotations Example].
  The mappings of the classes should be in the hibernate.cfg.xml file
        <mapping class="com.shyarmal.hibernate.Driver"/>
        <mapping class="com.shyarmal.hibernate.License"/>

My License class.
===============================================================

package com.shyarmal.hibernate;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "license")
public class License {

    private Long id;
    private Date issueDate;
    private String country;
    private String category;

    private License() {
    }
   
    public License(Date issueDate, String country, String category) {
        this.issueDate = issueDate;
        this.country = country;
        this.category = category;
    }

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

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

    @Column(name = "issue_date", columnDefinition = "timestamp")
    public Date getIssueDate() {
        return issueDate;
    }

    public void setIssueDate(Date issueDate) {
        this.issueDate = issueDate;
    }

    @Column(name = "country")
    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Column(name = "category")
    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }
}
===============================================================

The Driver class should have an instance of the License class, if to form a one-to-one.
My Driver class
===============================================================

package com.shyarmal.hibernate;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "driver")
public class Driver {

    private Long id;
    private String name;
    private int age;
    private License license;

    private Driver() {
       
    }
   
    public Driver(String name, int age) {
        this.name = name;
        this.age = age;
    }
   
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long 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;
    }

    @OneToOne(cascade = CascadeType.ALL)
    public License getLicense() {
        return license;
    }

    public void setLicense(License license) {
        this.license = license;
    }

}

===============================================================

@OneToOne:- This annotation is to make the link between the corresponding field of the annotated class to that intended to be related in one-to-one mapping. The CascadeType is set to ALL which will reflect any change in the 'driver' table to the 'license' table. That means, for an instance if a driver is deleted his license will also be deleted correspondingly.


thanks,
Shyarmal.

Saturday, August 27, 2011

Hibernate Annotations with Collections (List)

Following class illustrates how to model a java.util.List in hibernate with annotations. The subjects that a student takes are given in a list. So the 'Student' class is having an instance of List of String's. This can only be used to model collections of Java built-in types.
 
package com.shyarmal.hibernate;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;

@Entity
public class Student {

    private Long id;
    private String college;
    private List<String> subjects;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
   
    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "college")
    public String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }
   
    @ElementCollection(fetch = FetchType.LAZY)
    @JoinTable(name = "student_subjects",
       joinColumns = {@JoinColumn(name = "student_id")})
    public List<String> getSubjects() {
        return subjects;
    }

    public void setSubjects(List<String> subjects) {
        this.subjects = subjects;
    }
}


Annotations used to handle the scenario;
  • @ElementCollection:- Informs that the instance annotated should be considered as a Java collection type. The optional attribute 'fetch' may be given to stress how the collection should be loaded [either lazy (the default) or eager]
  • @JoinTable:- Used to explicitly specify the properties of the table which joins the collection data with the entity in concern. Name of the joining column also can be given, which links to the primary key of the entity. Inverse joining column attribute should not be specified in this case.

thanks,
Shyarmal.

Hibernate Inheritance with Annotations

 There are a few approaches to deal with inheritance in hibernate. The technique discussed in this post accommodates all in one table.
  I'm having an abstract class, 'Person' and two of it's subclasses, 'Student' and 'Employee'. Both 'Student' and 'Employee' information is to be stored in a single table, named 'person'.

==================================================================
package com.shyarmal.hibernate;

import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;

@Entity
@Table(name = "person")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "person_type", discriminatorType = DiscriminatorType.STRING)
public abstract class Person {

    private Long id;
    protected String nic;
    protected int age;
    protected String name;
    protected char sex;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
   
    public void setId(Long id) {
        this.id = id;
    }
   
    @Column(name = "nic", unique = true, nullable =false)
    public String getNic() {
        return nic;
    }

    public void setNic(String nic) {
        this.nic = nic;
    }

    @Column(name = "age")
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Column(name = "name", nullable = false, length = 30)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "gender", length = 2, nullable = false)
    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

===================================================================

  First, we'll have a look at the 'Person' class. Here I'll only discuss what's done to accomplish inheritance [For other basic information, refer to Hinernate Annotations Example].  The annotation, @Inheritance denotes inheritance and there are subclasses of person to be mapped. Moreover all 'Person' instances will be available in a single database table, since the inheritance strategy used is  'InheritanceType.SINGLE_TABLE'.   
   @DiscriminatorColumn is mandatory in this approach. It forms a new column in the database with the name specified in the 'name' attribute. The discriminator column is used to Identify the type of the record (in our example where a record is of type 'Student' or 'Employee'). The attribute 'discriminatorType' states the type of the discriminator column.
   I have posted my 'Student' and 'Employee' classes below.

=================================================================== 
package com.shyarmal.hibernate;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;

@Entity
@DiscriminatorValue("student")
public class Student extends Person {

    private String college;
    private List<String> subjects;

    @Column(name = "college", nullable = false, columnDefinition = "varchar(20) default 'unknown'")
    public String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }
   
    @ElementCollection(fetch = FetchType.LAZY)
    @JoinTable(name = "student_subjects", joinColumns = {@JoinColumn(name = "person_id")})
    public List<String> getSubjects() {
        return subjects;
    }

    public void setSubjects(List<String> subjects) {
        this.subjects = subjects;
    }

    @Override
    public String toString() {
        return String.format("student: nic [%s], college [%s], name [%s], age [%d]", nic, college, name, age);
    }
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

package com.shyarmal.hibernate;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("employee")
public class Employee extends Person {

    private String company;
    private double salary;

    @Column(name = "company", nullable = false, columnDefinition = "varchar(20) default 'unknown'")
    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    @Column(name = "salary", nullable = false, columnDefinition = "double(8, 2) default '0.0'")
    public double getSalary() {
        return salary;
    }

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

    @Override
    public String toString() {
        return String.format("employee: nic [%s], company [%s], name [%s], age [%d]", nic, company, name, age);
    }
}
===================================================================

@DiscriminatorValue annotation should be present in the subclasses. The discriminator value is what's saved in the discriminator column, which was discussed above [in our example if an employee is saved the discriminator column will have the value 'employee' and for a student the value will be 'student']. Notice 'columnDefinition' attribute in @Column in subclasses. If a column is declared not to be nullable, then a default value for the corresponding field should be given as done in the example. If not hibernate does not create the table. 'Student' class has a list of subjects. The methodology used is described here.

Below is the hibernate.cfg.xml used.
=================================================================== 

<?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="connection.url">jdbc:mysql://localhost/test</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="connection.pool_size">1</property>
        <property name="current_session_context_class">thread</property>
        <mapping class="com.shyarmal.hibernate.Person"/>
        <mapping class="com.shyarmal.hibernate.Student"/>
        <mapping class="com.shyarmal.hibernate.Employee"/> 
    </session-factory>
</hibernate-configuration>


thanks,
Shyarmal.