0

I have a Spring/Hibernate project with entities defined using both hbm's and annotations.

When I am trying to deploy the project I get the following error message:

Caused by: org.hibernate.MappingException: Following super classes referenced in extends not found: hibernate.examples.model.Task
    at org.hibernate.cfg.Configuration.processExtendsQueue(Configuration.java:1768) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1690) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    ....................

The reason I have to keep using both is because some of the code is legacy and I cannot touch that at the moment. And we have to start using the annotations for creating any new entities moving forward.

This is how I am registering both kinds of mappings into the configuration:

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan("hibernate.examples.model", "models");
        em.setMappingResources("Task.hbm.xml");
        em.setMappingResources("HealthTask.hbm.xml");

        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(hibernateProperties());
        return em;
    }

The setPackagesToScan method scans for all the entities marked by annotations and setMappingResources is supposed to take care of the hbm files.

When I comment out the em.setMappingResources..... then the project gets deployed without any issues.

Also, the weird part to note is that when I run it as a standalone application i.e. using public static void main(String[] args) I do not have any issues working with both kinds of mapping. All the entities get registered and schema gets created.

Here is how I run the project:

public class ConceptRunner {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();

        ctx.register(HibernateConfiguration.class);
        ctx.refresh();

        System.exit(0);

    }

}

But as soon as I deploy the project, it fails to register the hbm files.

Here are my hbm files:

Task.hbm.xml

<hibernate-mapping>
    <class name="hibernate.examples.model.Task" table="TASKS" abstract="true">
        <id name="id" type="java.lang.Long">
            <column name="ID" precision="22" scale="0"/>
            <generator class="identity"/>
        </id>
        <discriminator column="TYPE" type="string"/>
        <property name="type" type="java.lang.String" insert="false" update="false">
            <column name="TYPE" length="10"/>
        </property>
        <property name="name" type="java.lang.String">
            <column name="NAME" length="50"/>
        </property>
        <property name="description" type="java.lang.String">
            <column name="DESCRIPTION" length="250"/>
        </property>
    </class>
</hibernate-mapping>

HealthTask.hbm.xml

<hibernate-mapping>
    <subclass name="hibernate.examples.model.HealthTask"
              extends="hibernate.examples.model.Task" discriminator-value="HEALTH">
        <property name="requestServed" type="java.lang.Long">
            <column name="REQUEST_SERVED"/>
        </property>
        <property name="requestFailed" type="java.lang.Long">
            <column name="REQUEST_FAILED"/>
        </property>
        <property name="totalRequest" type="java.lang.Long">
            <column name="TOTAL_REQUEST"/>
        </property>
    </subclass>
</hibernate-mapping>

Please let me know if there is any other information that you would like from me..

Cœur
  • 37,241
  • 25
  • 195
  • 267
Nick Div
  • 5,338
  • 12
  • 65
  • 127
  • 1
    You should call `setMappingResources` once. It is a `set` not an `add`. In short the only one registered is the `HelathTask.hbm.xml` because it overrides the previously set values... Instead do `setMappingResources("Task.hbm.xml", "HealthTask.hbm.xml");` – M. Deinum Sep 06 '17 at 05:44
  • post your project structure for once – Anmol Bhardwaj Sep 06 '17 at 06:39
  • @M.Deinum I cant thank you enough. It had me stuck for the longest time. Appreciate it. – Nick Div Sep 06 '17 at 11:39
  • Stack Overflow a question and answer site, not a question and solution in question site. Thus write an answer, instead of writing the solution into the question. – Tom Sep 06 '17 at 11:45
  • @M.Deinum If you post an answer, I will remove mine and accept yours. – Nick Div Sep 06 '17 at 14:08

1 Answers1

1
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan("hibernate.examples.model", "models");
    em.setMappingResources("Task.hbm.xml");
    em.setMappingResources("HealthTask.hbm.xml");

    final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    em.setJpaProperties(hibernateProperties());
    return em;
}

As the setMappingResources is a setter each call to it will replace the current set of resources. As you are calling it twice in your code only the last one will remain (the HealthTask.hbm.xml and the Task.hbm.xml will be ignored).

If you take a look at the setMappingResources of the LocalContainerEntityManagerFactoryBean you will notice it takes a String... as an argument (a varargs argument to be exact).

So instead of calling it twice call it once with 2 arguments.

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan("hibernate.examples.model", "models");
    em.setMappingResources("Task.hbm.xml", "HealthTask.hbm.xml");

    final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    em.setJpaProperties(hibernateProperties());
    return em;
}
M. Deinum
  • 115,695
  • 22
  • 220
  • 224