java - mvc - Spring 3.1 Excepción de Hibernate 4 para herencia
spring java tutorial (3)
Hola, acabo de empezar a utilizar Spring, con Hibernate4 y maven. Básicamente, mi jerarquía de clases es HUmanMicroTask se extiende desde MicroTask. En el futuro, puede haber varias otras clases que se extienden desde MicroTask. Estaba intentando tener una tabla por clase concreta, que es la forma más sencilla de ponerme en marcha con spring3 e hibernar 4. Sin embargo, cuando ejecuto mi código. Sigo recibiendo la siguiente excepción
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
Aunque he visto bastantes foros, no estoy seguro de decidir dónde estoy cometiendo el error. Mi clase MicroTask se ve de la siguiente manera:
@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
Mi clase HumanMicroTask se ve de la siguiente manera:
@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
Y mi config.xml se ve de la siguiente manera:
<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>
Mi configuración Maven
<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>
Amablemente ayúdenme. No estoy seguro de dónde estoy cometiendo el error.
Se debe a la columna Id en ambas clases. Elimine el Id de HumanMicroTask.
Tuve el mismo problema hace un tiempo, ya que su clase principal tiene una clave principal: ''Id'', cuando se generan las subclases generan automáticamente una clave externa con el nombre exacto de la clave primaria de sus padres
Ejemplo: (Pseudocódigo)
Definición de la entidad
Clase de padres
@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
}
Clase de niños:
@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;
}
Generación de tablas
La clase para padres asignará a esto
Tabla "abstract_person"
id: Int (clave principal)
nombre: Varchar
La clase infantil se asignará a esto:
Mesa "concrete_person"
profesión: Varchar
idPerson: int (Generado automáticamente, clave externa para la tabla principal y clase primaria de esta tabla)
// Suposiciones
Base de datos Mysql;
Implementación de Jpa 2 Hibernate;
NetBeans 7x Ide
para arreglar esto Retire @Id de la Subclase
en MicroTask mantener
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "MICROTASKID")
private String microTaskId;
en la Subclase HumanMicroTask eliminar
@Id
@Column(name = "HMTID")
private String humanMicroTaskid;