Spring/Hibernate 对实体使用注释和 hbm 混合时无法初始化 EntityManager
Spring/Hibernate fails to initialize the EntityManager when using mix of annotations and hbm for entities
我有一个 Spring/Hibernate 项目,其中包含使用 hbm 和注释定义的实体。
当我尝试部署项目时,我收到以下错误消息:
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.perform(EntityManagerFactoryBuilderImpl.java:857) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.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]
....................
我必须继续使用两者的原因是因为一些代码是遗留的,我目前无法触及。我们必须开始使用注释来创建任何向前发展的新实体。
这就是我将两种映射注册到配置中的方式:
@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;
}
setPackagesToScan
方法扫描所有由注释标记的实体,setMappingResources
应该处理 hbm 文件。
当我注释掉 em.setMappingResources.....
时,项目将顺利部署。
此外,需要注意的奇怪部分是,当我 运行 它作为一个独立的应用程序时,即使用 public static void main(String[] args)
我在使用这两种映射时都没有任何问题。所有实体都已注册并创建了架构。
这是我 运行 项目的方式:
public class ConceptRunner {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(HibernateConfiguration.class);
ctx.refresh();
System.exit(0);
}
}
但是一旦我部署项目,它就无法注册 hbm 文件。
这是我的 hbm 文件:
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>
健康Task.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>
如果您想从我这里得到任何其他信息,请告诉我..
@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;
}
因为 setMappingResources
是一个 setter 每次调用它都会替换当前的资源集。当您在代码中调用它两次时,只会保留最后一个(HealthTask.hbm.xml
和 Task.hbm.xml
将被忽略)。
如果你看一下 LocalContainerEntityManagerFactoryBean
的 setMappingResources
,你会注意到它需要一个 String...
作为参数(准确地说是可变参数)。
所以不要调用它两次,而是使用 2 个参数调用它一次。
@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;
}
我有一个 Spring/Hibernate 项目,其中包含使用 hbm 和注释定义的实体。
当我尝试部署项目时,我收到以下错误消息:
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.perform(EntityManagerFactoryBuilderImpl.java:857) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.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]
....................
我必须继续使用两者的原因是因为一些代码是遗留的,我目前无法触及。我们必须开始使用注释来创建任何向前发展的新实体。
这就是我将两种映射注册到配置中的方式:
@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;
}
setPackagesToScan
方法扫描所有由注释标记的实体,setMappingResources
应该处理 hbm 文件。
当我注释掉 em.setMappingResources.....
时,项目将顺利部署。
此外,需要注意的奇怪部分是,当我 运行 它作为一个独立的应用程序时,即使用 public static void main(String[] args)
我在使用这两种映射时都没有任何问题。所有实体都已注册并创建了架构。
这是我 运行 项目的方式:
public class ConceptRunner {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(HibernateConfiguration.class);
ctx.refresh();
System.exit(0);
}
}
但是一旦我部署项目,它就无法注册 hbm 文件。
这是我的 hbm 文件:
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>
健康Task.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>
如果您想从我这里得到任何其他信息,请告诉我..
@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;
}
因为 setMappingResources
是一个 setter 每次调用它都会替换当前的资源集。当您在代码中调用它两次时,只会保留最后一个(HealthTask.hbm.xml
和 Task.hbm.xml
将被忽略)。
如果你看一下 LocalContainerEntityManagerFactoryBean
的 setMappingResources
,你会注意到它需要一个 String...
作为参数(准确地说是可变参数)。
所以不要调用它两次,而是使用 2 个参数调用它一次。
@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;
}