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..
@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;
}