Pages

Mixing inheritance strategy

Mixing inheritance strategy

Till now, we have seen four type of inheritance strategy 
(1) Table per concrete class with implicit polymorphism
(2) Table per concrete class with union
(3) Table per class hierarchy
(4) Table per subclass 

Now, In this strategy, we can not mix above four type strategy to solve a particular inheritance mapping, we have to follow Mixing inheritance strategy. you can switch the mapping strategy for a particular subclass.

You can map a class hierarchy to a single table but for a particular subclass , you can switch to a separate table with foreign key mapping strategy (like a table per subclass).

We will follow the same example which we have defined in my previous post. we have only changed the xml mapping metadata file .

<hibernate-mapping package="mixing.inheritance.strategy">
<class name="CreditCardHolder" table="CREDIT_CARD_HOLDER" dynamic-insert="true" dynamic-update="true">
<id name="creditCardHolderId" column="CREDIT_CARD_HOLDER_ID" type="long">
<generator class="increment"/>
</id>
<discriminator column="DIS_CREDIT_CARD_HOLDER_VAL" type="string"/>
<property name="owner" column="OWNER"/>
 
<subclass name="CreditCardDetails" discriminator-value="CC">
<join table="CREDIT_CARD_DETAILS">
<key column="CREDIT_CARD_ID"/>
<property name="number" column="CREDIT_CARD_NUMBER"/>
<property name="expMonth" column="EXP_MONTH"/>
<property name="expYear" column="EXP_YEAR"/>
</join>
</subclass>
<subclass name="BankAccountDetails" discriminator-value="BA">
<property name="account" column="ACCOUNT_TYPE"/>
<property name="bankName" column="BANK_NAME"/>
</subclass>
</class>
</hibernate-mapping>

now, try to run the HibernateTest class and see the generated hibernate SQL statement on console.

15:13:17,057 INFO HibernateTest:20 - starting of main method
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.0rc1
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Environment <clinit>
INFO: using CGLIB reflection optimizer
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: mixing/inheritance/strategy/CreditCardHolder.hbm.xml
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: mixing.inheritance.strategy.CreditCardHolder -> CE_CREDIT_CARD_HOLDER
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.HbmBinder bindSubclass
INFO: Mapping subclass: mixing.inheritance.strategy.CreditCardDetails -> CE_CREDIT_CARD_HOLDER
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.HbmBinder bindJoin
INFO: Mapping class join: mixing.inheritance.strategy.CreditCardDetails -> CE_CREDIT_CARD_DETAILS
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.HbmBinder bindSubclass
INFO: Mapping subclass: mixing.inheritance.strategy.BankAccountDetails -> CE_CREDIT_CARD_HOLDER
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 3:13:17 PM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Maximum outer join fetch depth: 2
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Oct 16, 2012 3:13:17 PM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Oct 16, 2012 3:13:17 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 16, 2012 3:13:17 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {password=****, autocommit=true, user=root}
Oct 16, 2012 3:13:17 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 16, 2012 3:13:17 PM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
15:13:17,335 INFO MLog:80 - MLog clients using log4j logging.
15:13:17,560 INFO C3P0Registry:204 - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
15:13:17,617 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@6b3054d7 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@78ac60c7 [ 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 -> 1bs1yqt8qt4dh851rzvoq2|107f7fe, 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@6b536310 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qt4dh851rzvoq2|18374c9, 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 -> 1bs1yqt8qt4dh851rzvoq2|184e990, numHelperThreads -> 3 ]
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): enabled
Oct 16, 2012 3:13:17 PM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
Oct 16, 2012 3:13:17 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 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.EhCacheProvider
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: enabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Oct 16, 2012 3:13:17 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Oct 16, 2012 3:13:17 PM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Oct 16, 2012 3:13:17 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 16, 2012 3:13:18 PM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Oct 16, 2012 3:13:18 PM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 16, 2012 3:13:18 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 16, 2012 3:13:18 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: Running hbm2ddl schema export
Oct 16, 2012 3:13:18 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Oct 16, 2012 3:13:18 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 16, 2012 3:13:18 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {password=****, autocommit=true, user=root}
Oct 16, 2012 3:13:18 PM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 16, 2012 3:13:18 PM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
15:13:18,239 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@5f720ff0 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@5f671008 [ 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 -> 1bs1yqt8qt4dh851rzvoq2|c19fb, 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@8d7cdaa2 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8qt4dh851rzvoq2|c15a3f, 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 -> 1bs1yqt8qt4dh851rzvoq2|b83bd, numHelperThreads -> 3 ]
Oct 16, 2012 3:13:18 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
Oct 16, 2012 3:13:18 PM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
Hibernate: insert into CE_CREDIT_CARD_HOLDER (OWNER, DIS_CREDIT_CARD_HOLDER_VAL, CREDIT_CARD_HOLDER_ID) values (?, 'CC', ?)
Hibernate: insert into CE_CREDIT_CARD_DETAILS (CREDIT_CARD_NUMBER, EXP_MONTH, EXP_YEAR, CREDIT_CARD_ID) values (?, ?, ?, ?)
Hibernate: insert into CE_CREDIT_CARD_HOLDER (OWNER, ACCOUNT_TYPE, BANK_NAME, DIS_CREDIT_CARD_HOLDER_VAL, CREDIT_CARD_HOLDER_ID) values (?, ?, ?, 'BA', ?)
Oct 16, 2012 3:13:18 PM org.hibernate.impl.SessionFactoryImpl close
INFO: closing

let's run the polymorphic query against CreditCardHolder class
   Query query = session.createQuery("from CreditCardHolder");
   List list = query.list();

It generates This SQL statement :

Hibernate: 
select creditcard0_.CREDIT_CARD_HOLDER_ID as CREDIT1_, 
creditcard0_.OWNER as OWNER0_, 
creditcard0_.ACCOUNT_TYPE as ACCOUNT4_0_, 
creditcard0_.BANK_NAME as BANK5_0_, 
creditcard0_1_.CREDIT_CARD_NUMBER as CREDIT2_1_, 
creditcard0_1_.EXP_MONTH as EXP3_1_, 
creditcard0_1_.EXP_YEAR as EXP4_1_, 
creditcard0_.DIS_CREDIT_CARD_HOLDER_VAL as DIS2_ 
from 
CE_CREDIT_CARD_HOLDER creditcard0_ 
left outer join CE_CREDIT_CARD_DETAILS creditcard0_1_ 
on creditcard0_.CREDIT_CARD_HOLDER_ID=creditcard0_1_.CREDIT_CARD_ID

If your class hierarchy is wide that time, outer join can be a major issue for this type of strategy. Than you have to switch different fetching strategy which execute a immediate SQL SELECT statement instead of outer join.

see the xml mapping metadata again,

<hibernate-mapping package="mixing.inheritance.strategy">
<class name="CreditCardHolder" table="CREDIT_CARD_HOLDER" dynamic-insert="true" dynamic-update="true">
<id name="creditCardHolderId" column="CREDIT_CARD_HOLDER_ID" type="long">
<generator class="increment"/>
</id>
<discriminator column="DIS_CREDIT_CARD_HOLDER_VAL"/>
<property name="owner" column="OWNER"/>
 
<subclass name="CreditCardDetails" discriminator-value="CC">
<join table="CREDIT_CARD_DETAILS" fetch="select">
<key column="CREDIT_CARD_ID"/>
<property name="number" column="CREDIT_CARD_NUMBER"/>
<property name="expMonth" column="EXP_MONTH"/>
<property name="expYear" column="EXP_YEAR"/>
</join>
</subclass>
<subclass name="BankAccountDetails" discriminator-value="BA">
<property name="account" column="ACCOUNT_TYPE"/>
<property name="bankName" column="BANK_NAME"/>
</subclass>
</class>
</hibernate-mapping>


7 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. thank you for the article

    if for example I have the following hierarchy

    Class A (class mother)
    (Class B and Class) Extends A

    Strategie table sub class:

    class name="A" table="a"
    joined-subclass name="B" table="B"
    joined-subclass name="C" table="C"
    /class





    if you want to mix the strategy table not in class and sub class table with discriminator :


    class name="A" table="a"
    joined-subclass name="B" table="B"
    class
    class name="c" table="c"
    subclass name="c"
    many-to-one
    set
    join
    .........
    join
    subclass
    class



    my question is how we can make the relationship between the class A is the class C
    that means if you want to add an instance of type C is automatically added to table A and table C

    Thank you for your help

    ReplyDelete
  3. • I very much enjoyed this article. Nice article thanks for given this information. I hope it useful to many Peopledata since Online Training india

    ReplyDelete
  4. • Nice and good article. It is very useful for me to learn and understand easily. Thanks for sharing your valuable information and time. Please keep updatingAzure Online Training Hyderabad

    ReplyDelete
  5. Happy to found this blog. Good Post!. It was so good to read and useful to improve my knowledge as updated one, keep blogging. Hibernate Training in Electronic City
    Java Training in Electronic City

    ReplyDelete