43

Hi I have just started using Spring , with Hibernate4 and maven. Basically my class hierarchy is HUmanMicroTask extends from MicroTask . In future there may be several other classes extending from MicroTask. I was trying to have a one table per concrete class which is the simplest way to get up and running with spring3 and hibernate 4. However when i run my code. I keep getting the following exception

13:11:52,260 ERROR TestContextManager:324 - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@6ef137d] to prepare test instance [HumanMicroTaskBaseHibernateTest@52c05d3b]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [database-config.xml]: Invocation of init method failed; nested exception is java.lang.ClassCastException: org.hibernate.mapping.UnionSubclass cannot be cast to org.hibernate.mapping.RootClass
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
    at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
    at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
    ... 24 more
Caused by: java.lang.ClassCastException: org.hibernate.mapping.UnionSubclass cannot be cast to org.hibernate.mapping.RootClass
    at org.hibernate.cfg.annotations.PropertyBinder.bind(PropertyBinder.java:212)
    at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:203)
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2013)
    at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:768)
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:687)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3431)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3385)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1337)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1727)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1778)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:184)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:314)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
    ... 38 more

Although I have seen quite a few forums, I am unabelt o decide on where I am making the mistake. My MicroTask class looks as follows :

@Entity
@Table(name = "MICROTASK")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class MicroTask {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(name = "MICROTASKID")
    private String microTaskId;
    @Column(name = "CREATIONDATE")
    private Date creationDate;
    @Column(name = "DESCRIPTION")
    private String description;

    public Date getCreationDate() {
        return creationDate;
    }
//More Getters and setters 

My HumanMicroTask Class looks as follows :

    @Entity
    @Table(name = "HUMANMICROTASK")
    @AttributeOverrides({
        @AttributeOverride(name="microTaskId", column=@Column(name="MICROTASKID")),
        @AttributeOverride(name="creationDate", column=@Column(name="CREATIONDATE")),
        @AttributeOverride(name="description", column=@Column(name="DESCRIPTION"))
    })
    public class HumanMicroTask extends MicroTask {


        @Column(name = "TITLE")
        private String title;
        @Column(name = "CHANNEL")
        private String channel;
        @Id
        @Column(name = "HMTID")
        private String humanMicroTaskid;

        public String getId() {
            return humanMicroTaskid;
        }
//More Getters and setters

And my config.xml looks as follows :

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        ">

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass">
            <value>${jdbc.driver.className}</value>
        </property>
        <property name="jdbcUrl">
            <value>${jdbc.url}</value>
        </property>
        <property name="user">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>

    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
        <property name="packagesToScan" value="com.hp.hpl.crowdcloud" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <!-- uncomment this for first time run -->
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>
    <tx:annotation-driven />

</beans>

My Maven Configuration

    <maven.test.failure.ignore>true</maven.test.failure.ignore>
    <org.springframework.version>3.1.0.RELEASE</org.springframework.version>
    <hibernate.version>4.1.1.Final</hibernate.version>
    <sl4j.version>1.5.6</sl4j.version>

Kindly help me out. I am not sure where I making the mistake.

Raveesh Sharma
  • 1,458
  • 5
  • 21
  • 37

4 Answers4

80

It is due to Id column in both classes. Remove the Id from HumanMicroTask.

dhamibirendra
  • 2,936
  • 21
  • 26
  • 2
    You needn't delete that part of the code from the question, now it's all incomprehensible. – fledglingCoder Nov 26 '13 at 11:29
  • 1
    Worked! Thank you. Why the error message isn't as suggestive as yours? – Vinícius Fonseca Apr 12 '15 at 15:08
  • 1
    Removing the `@Id` annotation from subclasses is enough, or you can also probably delete the field, getters and setters, because the inheritance strategy `InheritanceType.TABLE_PER_CLASS` requires you to use all the inherited columns in subclass table with exactly the same column names, so mapping can be inherited from super classes. Other inheritance strategies may require you to use different ID column name for each subentity, hence `@Id` mapping can't be inherited to subclasses and is declared explicitly. – Vlastimil Ovčáčík Aug 18 '15 at 14:41
  • 1
    This is old, you may not answer, but what if my subclass table also has an identity column? – Rig Oct 19 '15 at 15:58
  • @Rig why would you like to keep Id in the subclass? – dhamibirendra Dec 09 '15 at 04:18
  • 1
    @dhamibirendra Well, its their own identity column if I remember what I meant when I wrote that. Either way I sorted it out with being a little more explicit with my annotations – Rig Dec 09 '15 at 06:35
  • @Rig could you expand on "being a little more explicit with my annotations"? I think I'm having the same problem, as I need to have my own identity in a subclass but I don't have a solution yet. – user1712376 Dec 27 '15 at 09:18
11

to fix this Remove @Id from Subclass

in MicroTask keep

   @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(name = "MICROTASKID")
    private String microTaskId;

in Subclass HumanMicroTask remove

   @Id
    @Column(name = "HMTID")
    private String humanMicroTaskid;
nizar ouerghi
  • 1,503
  • 1
  • 13
  • 12
8

I had the same problem some time ago, since your parent class has a primary key: 'Id', when the subclasses are generated they automatically generate a foreign key with the exact name of their parent's primary key

Example: (Pseudocode)

Entity Definition

Parent Class

  @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    @Table(name = "abstract_person", catalog = "catalog", schema = "")
    class AbstractPerson{

        //Primary Key
        @Id
        @Column(name = "idPerson")
        int idPerson;

        @Basic
        @Column(name = "name")
        String name;

        //corresponding getters and setters
    }

Child Class:

 @Entity
    @Table(name = "concrete_person", catalog = "catalog", schema = "")
    class ConcretePerson extends AbstractPerson{

       //No id or primary key is defined here

        @Basic
        @Column(name="profession")
        String profession;

    }

Table Generation

Parent class will map to this

Table "abstract_person"
id: Int (primary key)
name: Varchar

Child class will map to this:


Table "concrete_person"
profession: Varchar
idPerson: int (Automatically generated, foreign key to parent table and primary class of this table)

//Assumptions
Mysql database;
Jpa 2 Hibernate Implementation;
NetBeans 7x Ide

0

For TABLE_PER_CLASS hierarchy, the child class inherit the unique key from the parent and so we should not mention unique key constraint in child entity.

Remove the primary key annotations and this worked well for me.

VIrtual Host
  • 69
  • 1
  • 2