javahibernatejpa-2.0hibernate-5.x

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

  • 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.