Pages

Table per subclass

Table per subclass

By this strategy, you can represent inheritance relationship as a relational foreign key associations. Every class (including abstract class) has its own database table. table contains coulumns only for properties declared by subclass itself and  primary key of the sub class table is also a foreign key of the superclass table.

Again, we follow the same example which we referred in my previous post with some modification, we have added the identifier properties to both classes CreditCardDetails and BankAccountDetails and marked superclass as abstract.

public abstract class CreditCardHolder {
private Long creditCardHolderId;
private String owner;
     //generate getters and setters method for above properties
}
public class CreditCardDetails extends CreditCardHolder {
private Long creditCardId;
private String number;
private String expMonth;
private String expYear;
        //generate getters and setters method for above properties
}
public class BankAccountDetails extends CreditCardHolder {
private Long bankAccountId;
private String account;
private String bankName;
       //generate getters and setters method for above properties
}

also we have modified the CreditCardHolder.hbm.xml file. Now, there is no need to mentioned discriminator   column in the database table.

<hibernate-mapping package="table.per.subclass">
<class name="CreditCardHolder" dynamic-insert="true" dynamic-update="true">
<id name="creditCardHolderId" column="CREDIT_CARD_HOLDER_ID" type="long">
<generator class="increment"/>
</id>
<property name="owner" column="OWNER"/>
<joined-subclass name="CreditCardDetails" table="CREDIT_CARD_DETAILS">
      <!-- The key element is mandatory to share the foreign key relationship with superclass primary key -->
<key column="CREDIT_CARD_ID"/>
<property name="number" column="CREDIT_CARD_NUMBER"/>
<property name="expMonth" column="EXP_MONTH"/>
<property name="expYear" column="EXP_YEAR"/>
</joined-subclass>
<joined-subclass name="BankAccountDetails" table="BANK_ACCOUNT_DETAILS">
<key column="BANK_ACCOUNT_ID"/>
<property name="account" column="ACCOUNT_TYPE"/>
<property name="bankName" column="BANK_NAME"/>
</joined-subclass>
</class>
</hibernate-mapping>

if you run the following code, 
public class HibernateTest {
private final static Logger LOGGER = Logger.getLogger(HibernateTest.class); 
/**
* @param args
*/
public static void main(String[] args) {
LOGGER.info("starting of main method");
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction txn = session.beginTransaction();
CreditCardDetails creditCard = new CreditCardDetails();
creditCard.setNumber("3423243234342");
creditCard.setOwner("Sachin Sharma");
creditCard.setExpMonth("10/18");
creditCard.setExpYear("2018");
BankAccountDetails bankAccountDetails = new BankAccountDetails();
bankAccountDetails.setAccount("saving");
bankAccountDetails.setBankName("SBI");
bankAccountDetails.setOwner("Sachin Sharma");
session.saveOrUpdate(creditCard);
session.saveOrUpdate(bankAccountDetails);

txn.commit();
session.close();
HibernateUtil.shutDown();
}
}
Now, value of the superclass properties are saved in the superclass table and value of the subclass properties are saved in the subclass tables. two row are linked together by their shared primary key value.

subclass instances should be retrieve by joining the sublcass table with superclass table.\
The advantage of this strategy is , the schema is normalized.

See the hibernate generated SQL statements as follows :

11:55:05,277 INFO HibernateTest:20 - starting of main method
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.0rc1
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Environment <clinit>
INFO: using CGLIB reflection optimizer
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: table/per/subclass/CreditCardHolder.hbm.xml
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: table.per.subclass.CreditCardHolder -> CREDITCARDHOLDER
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.HbmBinder bindJoinedSubclass
INFO: Mapping joined-subclass: table.per.subclass.CreditCardDetails -> CE_CREDIT_CARD_DETAILS
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.HbmBinder bindJoinedSubclass
INFO: Mapping joined-subclass: table.per.subclass.BankAccountDetails -> CE_BANK_ACCOUNT_DETAILS
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 11:55:05 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Maximum outer join fetch depth: 2
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Oct 16, 2012 11:55:05 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Oct 16, 2012 11:55:05 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Oct 16, 2012 11:55:05 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 16, 2012 11:55:05 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {autocommit=true, password=****, user=root}
Oct 16, 2012 11:55:05 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 16, 2012 11:55:05 AM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
11:55:05,562 INFO MLog:80 - MLog clients using log4j logging.
11:55:05,806 INFO C3P0Registry:204 - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
11:55:05,863 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@b0203cb4 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@8e8a79c7 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8qsxalh4mtgoze|e40317, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@af526d1c [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qsxalh4mtgoze|1d4b0e9, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {autocommit=true, password=******, user=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qsxalh4mtgoze|1be098f, numHelperThreads -> 3 ]
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): enabled
Oct 16, 2012 11:55:06 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
Oct 16, 2012 11:55:06 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.EhCacheProvider
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: enabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Oct 16, 2012 11:55:06 AM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Oct 16, 2012 11:55:06 AM net.sf.ehcache.config.Configurator configure
WARNING: No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/D:/Anuj/Jars/HibernateLib/ehcache-1.1.jar!/ehcache-failsafe.xml
Oct 16, 2012 11:55:06 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Oct 16, 2012 11:55:06 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 11:55:06 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 11:55:06 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: Running hbm2ddl schema export
Oct 16, 2012 11:55:06 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Oct 16, 2012 11:55:06 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 16, 2012 11:55:06 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {autocommit=true, password=****, user=root}
Oct 16, 2012 11:55:06 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 16, 2012 11:55:06 AM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
11:55:06,515 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@d956e602 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@ae930154 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8qsxalh4mtgoze|1cb63fd, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@d962f213 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qsxalh4mtgoze|988edd, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {autocommit=true, password=******, user=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qsxalh4mtgoze|995893, numHelperThreads -> 3 ]
Oct 16, 2012 11:55:07 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
Oct 16, 2012 11:55:07 AM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
Hibernate: insert into CREDITCARDHOLDER (OWNER, CREDIT_CARD_HOLDER_ID) values (?, ?)
Hibernate: insert into CE_CREDIT_CARD_DETAILS (CREDIT_CARD_NUMBER, EXP_MONTH, EXP_YEAR, CREDIT_CARD_ID) values (?, ?, ?, ?)
Hibernate: insert into CREDITCARDHOLDER (OWNER, CREDIT_CARD_HOLDER_ID) values (?, ?)
Hibernate: insert into CE_BANK_ACCOUNT_DETAILS (ACCOUNT_TYPE, BANK_NAME, BANK_ACCOUNT_ID) values (?, ?, ?)
Oct 16, 2012 11:55:07 AM org.hibernate.impl.SessionFactoryImpl close
INFO: closing

If you run the following query against the superclass, 

Query query = session.createQuery("from CreditCardHolder");
List list = query.list();

Hibernate generates the following SQL statements,

Oct 16, 2012 12:22:36 PM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
Hibernate: select creditcard0_.CREDIT_CARD_HOLDER_ID as CREDIT1_, 
creditcard0_.OWNER as OWNER0_, 
creditcard0_1_.CREDIT_CARD_NUMBER as CREDIT2_1_, 
creditcard0_1_.EXP_MONTH as EXP3_1_, 
creditcard0_1_.EXP_YEAR as EXP4_1_, 
creditcard0_2_.ACCOUNT_TYPE as ACCOUNT2_2_, 
creditcard0_2_.BANK_NAME as BANK3_2_, 
case 
when creditcard0_1_.CREDIT_CARD_ID is not null then 1 
when creditcard0_2_.BANK_ACCOUNT_ID is not null then 2 
when creditcard0_.CREDIT_CARD_HOLDER_ID is not null then 0 
end as clazz_ 
from CREDITCARDHOLDER creditcard0_ 
left outer join CE_CREDIT_CARD_DETAILS creditcard0_1_ 
on creditcard0_.CREDIT_CARD_HOLDER_ID=creditcard0_1_.CREDIT_CARD_ID 
left outer join CE_BANK_ACCOUNT_DETAILS creditcard0_2_ 
on creditcard0_.CREDIT_CARD_HOLDER_ID=creditcard0_2_.BANK_ACCOUNT_ID

Oct 16, 2012 12:22:36 PM org.hibernate.impl.SessionFactoryImpl close
INFO: closing

SQL case statment checks the existence of rows in the subclass tables and hibernate executes this query with Left Outer join.




Table per class hierarchy

Table per class hierarchy

In this strategy, properties of subclasses is mapped to columns of one database table i.e whole class  hierarchy can be mapped to a single table. concrete sub-class (which was represented a row in a table) now can be represented by the value of discriminator column.

This strategy performs well for polymorphic and non-polymorphic queries.

Note: This strategy has one major problem, columns for properties declared by subclasses must be declared as nullable and normalization is second important issue.

Let's follow the same example in my previous post, we have done some modification according to this strategy. Now, we have one table (CREDIT_CARD_HOLDER) for CreditCardHolder class and this class is not abstract.

See the modification in CreditCardHolder.hbm.xml file,


<hibernate-mapping package="table.per.concrete_class">
<class name="CreditCardHolder" dynamic-insert="true" dynamic-update="true">
<id name="creditCardHolderId" column="CREDIT_CARD_HOLDER_ID" type="long">
<generator class="increment"/>
</id>

<!-- This element must be the first element after the id element in this mapping file -->
<discriminator column="DIS_CREDIT_CARD_HOLDER_VALUE"/>

<property name="owner" column="OWNER"/>
 
<subclass name="CreditCardDetails" discriminator-value="CC">
<property name="number" column="CREDIT_CARD_NUMBER"/>
<property name="expMonth" column="EXP_MONTH"/>
<property name="expYear" column="EXP_YEAR"/>
</subclass>

<subclass name="BankAccountDetails" discriminator-value="BA">
<property name="account" column="ACCOUNT_TYPE"/>
<property name="bankName" column="BANK_NAME"/>
</subclass>
</class>
</hibernate-mapping>

we have added a discriminator element in this xml mapping metadata, it is not a property in any class in the hierarchy. This column is used to distinguish between persistent classes, it is internally used by hibernate.

If you run the HibernateTest.java class which we have mentioned in my previous post. That time, it generates the following hibernate SQL statement at console.


09:51:35,006 INFO HibernateTest:22 - starting of main method
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.0rc1
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Environment <clinit>
INFO: using CGLIB reflection optimizer
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: table/per/concrete_class/CreditCardHolder.hbm.xml
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: table.per.concrete_class.CreditCardHolder -> CREDITCARDHOLDER
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.HbmBinder bindSubclass
INFO: Mapping subclass: table.per.concrete_class.CreditCardDetails -> CREDITCARDHOLDER
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.HbmBinder bindSubclass
INFO: Mapping subclass: table.per.concrete_class.BankAccountDetails -> CREDITCARDHOLDER
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 9:51:35 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Maximum outer join fetch depth: 2
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Oct 16, 2012 9:51:35 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Oct 16, 2012 9:51:35 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 16, 2012 9:51:35 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {autocommit=true, user=root, password=****}
Oct 16, 2012 9:51:35 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 16, 2012 9:51:35 AM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
09:51:35,286 INFO MLog:80 - MLog clients using log4j logging.
09:51:35,521 INFO C3P0Registry:204 - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
09:51:35,577 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@19d8fa13 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@8cc667b0 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8qssvro27bn6e7|186e8cb, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@d167c8b4 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qssvro27bn6e7|aa91ef, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {autocommit=true, user=******, password=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qssvro27bn6e7|8487ba, numHelperThreads -> 3 ]
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): enabled
Oct 16, 2012 9:51:35 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
Oct 16, 2012 9:51:35 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.EhCacheProvider
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: enabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Oct 16, 2012 9:51:35 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Oct 16, 2012 9:51:35 AM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Oct 16, 2012 9:51:35 AM net.sf.ehcache.config.Configurator configure
WARNING: No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/D:/Anuj/Jars/HibernateLib/ehcache-1.1.jar!/ehcache-failsafe.xml
Oct 16, 2012 9:51:36 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Oct 16, 2012 9:51:36 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 9:51:36 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 9:51:36 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: Running hbm2ddl schema export
Oct 16, 2012 9:51:36 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Oct 16, 2012 9:51:36 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 16, 2012 9:51:36 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {autocommit=true, user=root, password=****}
Oct 16, 2012 9:51:36 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 16, 2012 9:51:36 AM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
09:51:36,197 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@1b5d676a [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@23fb0718 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8qssvro27bn6e7|264dde, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@2442a798 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qssvro27bn6e7|21351e, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {autocommit=true, user=******, password=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qssvro27bn6e7|76cfab, numHelperThreads -> 3 ]
Oct 16, 2012 9:51:36 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
Oct 16, 2012 9:51:36 AM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
Hibernate: insert into CREDITCARDHOLDER (OWNER, CREDIT_CARD_NUMBER, EXP_MONTH, EXP_YEAR, DIS_CREDIT_CARD_HOLDER_VALUE, CREDIT_CARD_HOLDER_ID) values (?, ?, ?, ?, 'CC', ?)
Hibernate: insert into CREDITCARDHOLDER (OWNER, ACCOUNT_TYPE, BANK_NAME, DIS_CREDIT_CARD_HOLDER_VALUE, CREDIT_CARD_HOLDER_ID) values (?, ?, ?, 'BA', ?)
Oct 16, 2012 9:51:36 AM org.hibernate.impl.SessionFactoryImpl close
INFO: closing


Now, If you run the query against CreditCardHolder to retrieve the all instances of subclasses in the hierarchy.


Query query = session.createQuery("from CreditCardHolder");
List list = query.list();

please look the hibernate generated statments on console.

select creditcard0_.CREDIT_CARD_HOLDER_ID as CREDIT1_, 
creditcard0_.OWNER as OWNER0_, 
creditcard0_.CREDIT_CARD_NUMBER as CREDIT4_0_, 
creditcard0_.EXP_MONTH as EXP5_0_, 
creditcard0_.EXP_YEAR as EXP6_0_, 
creditcard0_.ACCOUNT_TYPE as ACCOUNT7_0_, 
creditcard0_.BANK_NAME as BANK8_0_, 
creditcard0_.DIS_CREDIT_CARD_HOLDER_VALUE as DIS2_ 
from CREDITCARDHOLDER creditcard0_

Note : If we do not specify the discriminator column value in the xml mapping metadata file, that time it automatically generates 'class' column (type String) in the table. see the hibernate generated SQL statement again.


INFO: Checking 0 named queries
Hibernate: insert into CREDITCARDHOLDER (OWNER, CREDIT_CARD_NUMBER, EXP_MONTH, EXP_YEAR, class, CREDIT_CARD_HOLDER_ID) values (?, ?, ?, ?, 'CC', ?)
Hibernate: insert into CREDITCARDHOLDER (OWNER, ACCOUNT_TYPE, BANK_NAME, class, CREDIT_CARD_HOLDER_ID) values (?, ?, ?, 'BA', ?)
Oct 16, 2012 11:12:50 AM org.hibernate.impl.SessionFactoryImpl close


The disadvantage of this strategy may be a major problem for designing , denormalization schema can be a major problem of this strategy.

Table per concrete class with union

Table per concrete class with union

I will follow the same example for this post which i referred in the previous post. Now, we have we have three class (including abstract class) and one xml mapping metadata.
This strategy solves mostly problem of "Table per concrete class with implicit polymorphism" and it shares common identifier of all sub-classes.

we have modified the entity classes as follows:


public abstract class CreditCardHolder {

private Long creditCardHolderId;
private String owner;
//generate getters and setters method for above properties
}

public class CreditCardDetails extends CreditCardHolder {

private String number;
private String expMonth;
private String expYear;
        //generate getters and setters method for above properties
}

public class BankAccountDetails extends CreditCardHolder {

private String account;
private String bankName;
        //generate getters and setters method for above properties
}


Note: CreditCardHolder class is abstract. if a class is not defined as abstract So we have to define a saperate table for that class in the database. 

Now, only one xml mapping metadata file is required.


<hibernate-mapping package="table.per.concrete_class.with.union">
<class name="CreditCardHolder" abstract="true" dynamic-insert="true" dynamic-update="true">
<id name="creditCardHolderId" column="CREDIT_CARD_HOLDER_ID" type="long">
<generator class="identity"/> <!-- or increment-->
</id>

<property name="owner" column="OWNER"/> 

<union-subclass name="CreditCardDetails" table="CREDIT_CARD_DETAILS">
<property name="number" column="CREDIT_CARD_NUMBER"/>
<property name="expMonth" column="EXP_MONTH"/>
<property name="expYear" column="EXP_YEAR"/>
</union-subclass>

<union-subclass name="BankAccountDetails" table="BANK_ACCOUNT_DETAILS">
<property name="account" column="ACCOUNT_TYPE"/>
<property name="bankName" column="BANK_NAME"/>
</union-subclass>
</class>
</hibernate-mapping>
If you run the following code, 

public class HibernateTest {
private final static Logger LOGGER = Logger.getLogger(HibernateTest.class); 
/**
* @param args
*/
public static void main(String[] args) {
LOGGER.info("starting of main method");
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction txn = session.beginTransaction();
CreditCardDetails creditCard = new CreditCardDetails();
creditCard.setNumber("3423243234342");
creditCard.setOwner("Sachin Sharma");
creditCard.setExpMonth("10/18");
creditCard.setExpYear("2018");
BankAccountDetails bankAccountDetails = new BankAccountDetails();
bankAccountDetails.setAccount("saving");
bankAccountDetails.setBankName("SBI");
bankAccountDetails.setOwner("Sachin Sharma");
session.saveOrUpdate(creditCard);
session.saveOrUpdate(bankAccountDetails);
txn.commit();
session.close();
HibernateUtil.shutDown();
}
}
See the Hibernate generated statements on console :

17:43:12,899 INFO HibernateTest:19 - starting of main method
Oct 15, 2012 5:43:12 PM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.0rc1
Oct 15, 2012 5:43:12 PM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
Oct 15, 2012 5:43:12 PM org.hibernate.cfg.Environment <clinit>
INFO: using CGLIB reflection optimizer
Oct 15, 2012 5:43:12 PM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
Oct 15, 2012 5:43:12 PM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Oct 15, 2012 5:43:12 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: table/per/concrete_class/with/union/CreditCardHolder.hbm.xml
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: table.per.concrete_class.with.union.CreditCardHolder -> CREDITCARDHOLDER
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.HbmBinder bindUnionSubclass
INFO: Mapping union-subclass: table.per.concrete_class.with.union.CreditCardDetails -> CE_CREDIT_CARD_DETAILS
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.HbmBinder bindUnionSubclass
INFO: Mapping union-subclass: table.per.concrete_class.with.union.BankAccountDetails -> CE_BANK_ACCOUNT_DETAILS
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 15, 2012 5:43:13 PM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Maximum outer join fetch depth: 2
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Oct 15, 2012 5:43:13 PM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Oct 15, 2012 5:43:13 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 15, 2012 5:43:13 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {autocommit=true, password=****, user=root}
Oct 15, 2012 5:43:13 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 15, 2012 5:43:13 PM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
17:43:13,169 INFO MLog:80 - MLog clients using log4j logging.
17:43:13,397 INFO C3P0Registry:204 - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
17:43:13,454 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@7b61fbf5 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@7d713a61 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8qruafse1ro6pj3|1340e79, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@28473f2d [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qruafse1ro6pj3|1e16028, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {autocommit=true, password=******, user=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qruafse1ro6pj3|d3e973, numHelperThreads -> 3 ]
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): enabled
Oct 15, 2012 5:43:13 PM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
Oct 15, 2012 5:43:13 PM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.EhCacheProvider
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: enabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Oct 15, 2012 5:43:13 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Oct 15, 2012 5:43:13 PM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Oct 15, 2012 5:43:13 PM net.sf.ehcache.config.Configurator configure
WARNING: No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/D:/Anuj/Jars/HibernateLib/ehcache-1.1.jar!/ehcache-failsafe.xml
Exception in thread "main" java.lang.ExceptionInInitializerError
at util.HibernateUtil.<clinit>(HibernateUtil.java:21)
at com.HibernateTest.main(HibernateTest.java:20)
Caused by: org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: table.per.concrete_class.with.union.BankAccountDetails
at org.hibernate.persister.entity.UnionSubclassEntityPersister.<init>(UnionSubclassEntityPersister.java:60)
at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:61)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:199)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1043)
at util.HibernateUtil.<clinit>(HibernateUtil.java:19)
... 1 more

If you see the comments, identity or increment generator strategy is not supporting for "table per concrete class with union strategy". referred this link for more details. 

So to fix this problem, change the generator strategy to "hilo" and run again HibernateTest class.

<hibernate-mapping package="table.per.concrete_class.with.union">
<class name="CreditCardHolder" abstract="true" dynamic-insert="true" dynamic-update="true">
<id name="creditCardHolderId" column="CREDIT_CARD_HOLDER_ID" type="long">
<generator class="hilo"/> <!-- identity and increment do not support for table per concrete class with union strategy --> 
</id>
<property name="owner" column="OWNER"/> 
<union-subclass name="CreditCardDetails" table="CREDIT_CARD_DETAILS">
<property name="number" column="CREDIT_CARD_NUMBER"/>
<property name="expMonth" column="EXP_MONTH"/>
<property name="expYear" column="EXP_YEAR"/>
</union-subclass>
<union-subclass name="BankAccountDetails" table="BANK_ACCOUNT_DETAILS">
<property name="account" column="ACCOUNT_TYPE"/>
<property name="bankName" column="BANK_NAME"/>
</union-subclass>
</class>
</hibernate-mapping>

Now, see again hibernate generated SQL statements on console,

17:52:40,427 INFO HibernateTest:19 - starting of main method
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.0rc1
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Environment <clinit>
INFO: using CGLIB reflection optimizer
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: table/per/concrete_class/with/union/CreditCardHolder.hbm.xml
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: table.per.concrete_class.with.union.CreditCardHolder -> CREDITCARDHOLDER
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.HbmBinder bindUnionSubclass
INFO: Mapping union-subclass: table.per.concrete_class.with.union.CreditCardDetails -> CE_CREDIT_CARD_DETAILS
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.HbmBinder bindUnionSubclass
INFO: Mapping union-subclass: table.per.concrete_class.with.union.BankAccountDetails -> CE_BANK_ACCOUNT_DETAILS
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 15, 2012 5:52:40 PM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Maximum outer join fetch depth: 2
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Oct 15, 2012 5:52:40 PM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Oct 15, 2012 5:52:40 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Oct 15, 2012 5:52:40 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 15, 2012 5:52:40 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {password=****, autocommit=true, user=root}
Oct 15, 2012 5:52:40 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 15, 2012 5:52:40 PM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
17:52:40,699 INFO MLog:80 - MLog clients using log4j logging.
17:52:40,925 INFO C3P0Registry:204 - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
17:52:40,982 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@baafe607 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@27e0928f [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8qrumlp5cog2xw|1340e79, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@d2b6975b [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qrumlp5cog2xw|1e16028, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {password=******, autocommit=true, user=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qrumlp5cog2xw|d3e973, numHelperThreads -> 3 ]
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): enabled
Oct 15, 2012 5:52:41 PM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
Oct 15, 2012 5:52:41 PM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.EhCacheProvider
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: enabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Oct 15, 2012 5:52:41 PM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Oct 15, 2012 5:52:41 PM net.sf.ehcache.config.Configurator configure
WARNING: No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/D:/Anuj/Jars/HibernateLib/ehcache-1.1.jar!/ehcache-failsafe.xml
Oct 15, 2012 5:52:41 PM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Oct 15, 2012 5:52:41 PM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 15, 2012 5:52:41 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 15, 2012 5:52:41 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: Running hbm2ddl schema export
Oct 15, 2012 5:52:41 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Oct 15, 2012 5:52:41 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 15, 2012 5:52:41 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {password=****, autocommit=true, user=root}
Oct 15, 2012 5:52:41 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 15, 2012 5:52:41 PM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
17:52:41,614 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@2cfe5f6b [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@6a6dce0 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8qrumlp5cog2xw|6ace81, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@c9f9734 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qrumlp5cog2xw|445dcf, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {password=******, autocommit=true, user=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qrumlp5cog2xw|10439a3, numHelperThreads -> 3 ]
Oct 15, 2012 5:52:41 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
Oct 15, 2012 5:52:41 PM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
Hibernate: insert into CE_CREDIT_CARD_DETAILS (OWNER, CREDIT_CARD_NUMBER, EXP_MONTH, EXP_YEAR, CREDIT_CARD_HOLDER_ID) values (?, ?, ?, ?, ?)
Hibernate: insert into CE_BANK_ACCOUNT_DETAILS (OWNER, ACCOUNT_TYPE, BANK_NAME, CREDIT_CARD_HOLDER_ID) values (?, ?, ?, ?)
Oct 15, 2012 5:52:41 PM org.hibernate.impl.SessionFactoryImpl close
INFO: closing

Now, if you execute a polymorphic query against superclass as soon above :

public class HibernateTest {


private final static Logger LOGGER = Logger.getLogger(HibernateTest.class);

/**
* @param args
*/
public static void main(String[] args) {
LOGGER.info("starting of main method");
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction txn = session.beginTransaction();
Query query = session.createQuery("from CreditCardHolder where");
List list = query.list();
txn.commit();
session.close();
HibernateUtil.shutDown();
}
}

If superclass is non-abstract than additional table is required to hold the instance of super class.The advantage of this mapping strategy are clear, It generate a single SELECT SQL statement with From clause sub-query retrieves all instances of CreditCardHolder from all concrete class tables. A union is required to map the projection over the same columns. we have to pad and fill the non-existent column with NULL.

INFO: schema export complete
Oct 15, 2012 6:06:30 PM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
Hibernate: 
select creditcard0_.CREDIT_CARD_HOLDER_ID as CREDIT1_, 
creditcard0_.OWNER as OWNER0_, 
creditcard0_.CREDIT_CARD_NUMBER as CREDIT1_1_, 
creditcard0_.EXP_MONTH as EXP2_1_, 
creditcard0_.EXP_YEAR as EXP3_1_, 
creditcard0_.ACCOUNT_TYPE as ACCOUNT1_2_, 
creditcard0_.BANK_NAME as BANK2_2_, 
creditcard0_.clazz_ as clazz_ 
from ( 
select null as BANK_NAME, 
EXP_YEAR, EXP_MONTH, CREDIT_CARD_NUMBER, 
OWNER, CREDIT_CARD_HOLDER_ID, null as ACCOUNT_TYPE, 
1 as clazz_ 
from CE_CREDIT_CARD_DETAILS 
union 
select BANK_NAME, null as EXP_YEAR, 
null as EXP_MONTH, null as CREDIT_CARD_NUMBER, 
OWNER, CREDIT_CARD_HOLDER_ID, 
ACCOUNT_TYPE, 2 as clazz_ 
from CE_BANK_ACCOUNT_DETAILS ) creditcard0_

Oct 15, 2012 6:06:30 PM org.hibernate.impl.SessionFactoryImpl close
INFO: closing