2011-04-14 9 views
5

estoy usando Hibernate 3.2.2 GA con HSQLDB 2,0 GA, y tengo una jerarquía de clase similar a la siguiente:Hibernate: org.hibernate.WrongClassException, la herencia SINGLE_TABLE y DiscriminatorFormula

@Entity 
@Table(name = "A_TABLE") 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorFormula(value = "case when CODE IN (1, 2, 3, 4) then 'TypeB' 
when CODE IN (5, 6, 7, 8) then 'TypeC' else NULL end") 
@org.hibernate.annotations.Entity(dynamicUpdate = true, dynamicInsert = true) 
public abstract class A{ 

(...) 

} 


@Entity 
@DiscriminatorValue("TypeB") 
public class B extends A { 

(...) 

} 


@Entity 
@DiscriminatorValue("TypeC") 
public class C extends A { 

(...) 

} 

estoy tratando de ejecutar la siguiente consulta HQL, que devuelve objetos de las clases B y C.

String hql = "from A a where a.someAttr = 3"; 
Query query = session.createQuery(hql); 

return query.list(); 

Sin embargo, me sale el siguiente error:

org.hibernate.WrongClassException: Object with id: 2 was not of the specified subclass: A (Discriminator: C  ) 

Lo más extraño es que el objeto con id 2 es una instancia de C ...

Googled para este error y he encontrado algunas personas que lo enfrentaron, ninguno usando InheritanceType.SINGLE_TABLE y DiscrimatorFormula, sin embargo. ¿Alguien ha tenido este problema?

+0

He pasado por esto. Si puede, adjunte un depurador a la clase 'Loader' de Hibernate o' SingleTableEntityPersister'. Este último está almacenando las subclases reales en el campo 'subclassesByDiscriminatorValue'. Comprueba las claves y compara lo que en realidad se pasó allí. Tu entrada se ve sospechosamente rellena con espacios en blanco. – mabi

Respuesta

0

El problema es que está obteniendo una lista de A e Hibernate no sabe lo suficiente como para crear B o C en una lista basada en la fórmula del discriminador. Afortunadamente, hay una anotación para tratar con esto.

Algunas personas llaman a esto un error, y estoy un poco inclinado a estar de acuerdo. En cualquier caso, la abstracción parece ser un poco permeable.

Agregue una anotación @ForceDiscriminator a la entidad principal (A) y es probable que funcione correctamente.

Esta solución es específica de Hibernate. No estoy seguro si el problema se extiende a JPA en general o si hay una solución JPA.

EDIT:

Esto no parece haber hecho el truco.

Puede valer la pena tratar de obtener el sql que está generando hibernate para usted.

Añadir

<property name="hibernate.show.sql" value="true" /> 

a su configuración de hibernación y ver qué pasa.

Obtener este sql con y sin la cláusula force podría dar pistas sobre qué hace exactamente la fuerza y ​​por qué no está funcionando.

No puedo pensar en nada más por el momento, excepto que el NULL en su fórmula de discriminación parece un poco arriesgado.

+1

no funcionó. Sigo recibiendo la WrongClassException después de haber agregado @ForceDiscriminator a A. ¿Alguna otra idea? ¡Gracias! – Porcho

1

Bueno, esto me picó la curiosidad: puede ser que sufre de this issue que dice:

The reason is the string is interpreted as a CHAR type rather than VARCHAR. We may change this behaviour in the future.

¿Se puede tratar de aplicar TRIM() en el resultado (en el interior del @DiscriminatorFormula) o prueba con otro DBMS? Esto no parece ser específico de Hibernate.

1

Lo resolví usando la columna DTYPE y la cláusula WHERE. Con su ejemplo, sería:

@Entity 
@WHERE(clause = "DTYPE = 'B'") 
public class B extends A { 
... 
} 


@Entity 
@WHERE(clause = "DTYPE = 'C'") 
public class C extends A { 
... 
}