'Hibernate 5 migration Issue with Multilevel Joined table Inheritance with Hibernate 5.4 DiscriminatorColumn

I am working on migrating a legacy Hibernate project from version 4.1 to 5.4. The code has Multilevel Joined table inheritance using a dedicated DiscriminatorColumn. The code was working fine in Hibernate 4 but throwing errors in Hibernate 5.

In-Short class hierarchy is like:

enter image description here

And, the code looks like:

First level Super class

@Entity
@Table(name="VideoTag")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "VideoTagType", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorOptions(force=true)
public abstract class VideoTag implements Cloneable {
    
    @Id
    @Column(name = "AdTagId")
    private Long adTagId;

    @Column(name = "VideoTagType")
    @Type(type = "enum_pub_video_tag_type")
    private VideoTagType videoTagType;
    
    //Non-important columns

    //Accessors 
}

Second level classes

Simple sub-class:
@Entity
@DiscriminatorValue(value = "2")
@Table(name = "OutstreamVideoTag")
public class OutStreamVideoTag extends VideoTag implements Cloneable {
        
    //Non-important columns

    //Accessors 
}

Complex sub-class/Second level super class
@Entity
@DiscriminatorValue(value = "1")
@Table(name = "InStreamVideoTag")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "InstreamVideoTagType", discriminatorType = DiscriminatorType.INTEGER)
public abstract class InStreamVideoTag extends VideoTag implements Cloneable {

    @Column(name = "InstreamVideoTagType")
    @Type(type = "enum_pub_instream_video_tag_type")
    private InstreamVideoTagType instreamVideoTagType;
    
    //Non-important columns

    //Accessors 
    
}

Last level Sub-classes

@Entity
@DiscriminatorValue(value = "1")
@Table(name = "RegularInStreamVideoTag")
public class RegularInStreamVideoTag extends InStreamVideoTag implements Cloneable {
    //Non-important columns

    //Accessors 
}

@Entity
@DiscriminatorValue(value = "2")
@Table(name = "InAppInstreamVideoTag")
public class InAppInstreamVideoTag extends InStreamVideoTag implements Cloneable {
        
    //Non-important columns

    //Accessors 
}

Errors

1. Save of RegularInStreamVideoTag entity is throwing the following error:

[DEBUG][SQL,qtp88259764-236] - 
    insert 
    into
        VideoTag
        (PlayerType, VideoTagType, AdTagId) 
    values
        (?, 1, ?)
Hibernate: 
    insert 
    into
        VideoTag
        (PlayerType, VideoTagType, AdTagId) 
    values
        (?, 1, ?)
[DEBUG][SqlExceptionHelper,qtp88259764-236] - could not insert: [com.domain.businessobject.publisher.RegularInStreamVideoTag] [insert into VideoTag (PlayerType, VideoTagType, AdTagId) values (?, 1, ?)]
com.microsoft.sqlserver.jdbc.SQLServerException: The index 3 is out of range.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:234) ~[mssql-jdbc-9.2.1.jre11.jar:?]
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setterGetParam(SQLServerPreparedStatement.java:1115) ~[mssql-jdbc-9.2.1.jre11.jar:?]
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setValue(SQLServerPreparedStatement.java:1129) ~[mssql-jdbc-9.2.1.jre11.jar:?]
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.setLong(SQLServerPreparedStatement.java:1429) ~[mssql-jdbc-9.2.1.jre11.jar:?]
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.setLong(HikariProxyPreparedStatement.java) ~[HikariCP-3.4.5.jar:?]
    at org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$1.doBind(BigIntTypeDescriptor.java:46) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:73) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:276) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:271) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrateId(AbstractEntityPersister.java:3040) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2998) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3289) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3825) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.engine.spi.ActionQueue.executeInserts(ActionQueue.java:461) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:258) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:330) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:194) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:179) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:100) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:75) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:99) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:616) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:609) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:604) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
    at com.domain.api.commons.dao.impl.AdTagDAOImpl.lambda$saveOrUpdateHeaderBiddingInfo$0(AdTagDAOImpl.java:918) ~[open-api-commons-dao-11.0.0.jar:11.0.0]
    at java.lang.Iterable.forEach(Iterable.java:75) ~[?:?]
    at com.domain.api.commons.dao.impl.AdTagDAOImpl.saveOrUpdateHeaderBiddingInfo(AdTagDAOImpl.java:918) ~[open-api-commons-dao-11.0.0.jar:11.0.0]
    at com.domain.api.commons.processor.publisher.impl.AdTagProcessorImpl.saveOrUpdateHeaderBiddingInfo(AdTagProcessorImpl.java:2428) ~[open-api-commons-processor-11.0.0.jar:11.0.0]
    at com.domain.publisher.endpoint.AdTagServiceEndpointImpl.createAdTag(AdTagServiceEndpointImpl.java:427) ~[classes/:?]
    at com.domain.publisher.endpoint.AdTagServiceEndpointImpl$$FastClassBySpringCGLIB$$9fdcaf7e.invoke(<generated>) ~[classes/:?]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.8.jar:5.3.8]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.8.jar:5.3.8]
    at com.domain.publisher.endpoint.AdTagServiceEndpointImpl$$EnhancerBySpringCGLIB$$cca3b878.createAdTag(<generated>) ~[classes/:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
    at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180) ~[cxf-core-3.1.12.jar:3.1.12]
    :
    :
    :
    at java.lang.Thread.run(Thread.java:834) [?:?]
[WARN ][SqlExceptionHelper,qtp88259764-236] - SQL Error: 0, SQLState: S1093
[ERROR][SqlExceptionHelper,qtp88259764-236] - The index 3 is out of range.
[DEBUG][HibernateTransactionManager,qtp88259764-236] - Participating transaction failed - marking existing transaction as rollback-only

2. Get any of the InStreamVideoTag subclass entities using Criteria.list() throwing the following error:

org.hibernate.InstantiationException: Cannot instantiate abstract class or interface:  : com.domain.businessobject.publisher.InStreamVideoTag
    at org.hibernate.tuple.PojoInstantiator.instantiate (PojoInstantiator.java:79)
    at org.hibernate.tuple.PojoInstantiator.instantiate (PojoInstantiator.java:105)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.instantiate (AbstractEntityTuplizer.java:705)
    at org.hibernate.persister.entity.AbstractEntityPersister.instantiate (AbstractEntityPersister.java:5204)
    at org.hibernate.internal.SessionImpl.instantiate (SessionImpl.java:1598)
    at org.hibernate.internal.SessionImpl.instantiate (SessionImpl.java:1582)
    at org.hibernate.loader.Loader.instanceNotYetLoaded (Loader.java:1755)
    at org.hibernate.loader.Loader.getRow (Loader.java:1616)
    at org.hibernate.loader.Loader.getRowFromResultSet (Loader.java:740)
    at org.hibernate.loader.Loader.getRowsFromResultSet (Loader.java:1039)
    at org.hibernate.loader.Loader.processResultSet (Loader.java:990)
    at org.hibernate.loader.Loader.doQuery (Loader.java:959)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections (Loader.java:349)
    at org.hibernate.loader.Loader.doList (Loader.java:2843)
    at org.hibernate.loader.Loader.doList (Loader.java:2825)
    at org.hibernate.loader.Loader.listIgnoreQueryCache (Loader.java:2657)
    at org.hibernate.loader.Loader.list (Loader.java:2652)
    at org.hibernate.loader.criteria.CriteriaLoader.list (CriteriaLoader.java:109)
    at org.hibernate.internal.SessionImpl.list (SessionImpl.java:1877)
    at org.hibernate.internal.CriteriaImpl.list (CriteriaImpl.java:370)
    at com.domain.api.commons.dao.impl.AdTagDAOImpl.getVideoTagsByAdTagGrp (AdTagDAOImpl.java:1002)
    at com.domain.api.commons.processor.publisher.impl.AdTagProcessorImpl.getVideoTagsByAdTagGrp (AdTagProcessorImpl.java:2423)
    at com.domain.publisher.endpoint.AdTagServiceEndpointImpl.getAdTagGroup (AdTagServiceEndpointImpl.java:72)
    at com.domain.publisher.endpoint.AdTagServiceEndpointImpl.searchAdTags (AdTagServiceEndpointImpl.java:1341)
    at com.domain.publisher.endpoint.AdTagServiceEndpointImpl$$FastClassBySpringCGLIB$$9fdcaf7e.invoke (<generated>)

Note: Tried changing the abstract InStreamVideoTag into a concrete class. It removed the error but it's not actually loading the RegularInStreamVideoTag type objects from DB, it's loading InStreamVideoTag objects only.

Thank you for reading!



Solution 1:[1]

Finally, it's resolved after removing all the @DiscriminatorColumn & @DiscriminatorValue annotations on all the classes. Looks like hibernate 5 is strict with the annotations. Now, the generated joined query for retrieving records is similar to Hibernate 4. It uses a special column named clazz using case statement to determine the inheritance type. This column will be used by hibernate internally.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Diablo