Estoy pensando en el diseño de tabla para una jerarquía de clases gestionada por Hibernate, y ciertamente la técnica de tabla por subclase me parece la más apropiada en un sentido general. Sin embargo, pensando en la lógica, tengo algunas preocupaciones sobre su rendimiento, especialmente a medida que aumenta el número de subclases.Eficiencia de la estrategia de herencia de tabla por subclase de Hibernate
para dar una muy breve (y clásico) ejemplo, digamos que usted tiene las siguientes clases:
captadorespublic abstract class Animal {
int pkey;
String name;
}
public class Dog extends Animal {
long numSlippersChewed; // int is not large enough...
}
public class Cat extends Animal {
short miceCaught; // ... but here int is far bigger than required :-)
}
(estoy elidiendo y definidores y de hibernación asignaciones etc., a suponer que son el caso obvio básico).
Las tablas de la base de datos para estas entidades tienen sentido, obtienes una buena desnormalización, etc. Sin embargo, ¿qué consulta hace Hibernate para extraer un animal individual? No puedo pensar en al menos dos casos en que esto puede ocurrir:
- Algunos otra entidad que tenga una correspondencia uno-a-uno (o uno-a-muchos), tales como un campo de una clase
Human
pet
. Esto almacenaría el pkey, por lo que cuando Hibernate recupera un objeto Humano, también tendrá que buscar el objeto correspondienteAnimal
. Cuando se le presente la clave del animal, ¿qué consulta (es) utilizará Hibernate para extraer y separar los datos reales de Animal, dado que podría residir en las tablasCat
oDog
? - HQL como
from Animal where name='Rex'
(supongamos que los nombres son únicos). Esto es similar al anterior ya que le permite identificar una fila en la tabla de superclase pero no sabe qué tabla de subclase debe inspeccionar para obtener más detalles. ¿HQL incluso le permite emitir una consultafrom
una clase abstracta? (El uso de elementos específicos de subclase funciona bien, por ejemplo,from Cat where miceCaught > 5
).
Se me ocurren dos maneras en que esto podría hacerse en SQL y ninguna de las dos parece bonita. Una es ejecutar una consulta exists
en cada tabla de subclase para el pkey dado y luego cargar desde la tabla que devolvió un hit. Alternativamente, Hibernate podría realizar una unión de consulta de unión horrible en todas las tablas, simulando esencialmente el esquema de tabla por jerarquía en que el conjunto de resultados incluiría atributos para todas las subclases posibles con las selecciones individuales de las tablas de subclase que devuelven null
para los argumentos irrelevantes. Este último caso probablemente incluso necesitaría agregar una columna de discriminador sintético para que Hibernate supiera qué tabla de subclase realmente devolvió la fila y, por lo tanto, en qué clase de Java deberían analizarse.
Las cosas se ponen más peludo también si usted tiene subtipos de tipos concretos:
public class Greyhound extends Dog {
float lifetimeRacingWinnings;
}
Ahora para una tecla p animal determinado, puede haber filas válidos en los Dog
yGreyhound
mesas, lo que significa que mi primer enfoque de chequear manualmente la clase que corresponde a un pkey se vuelve mucho más difícil.
La razón por la que estoy tan preocupado es que querré utilizar este enfoque en una jerarquía de clases con aproximadamente 70 clases con una cadena de anidación máxima de 4-5 niveles, por lo que realizar una consulta de unión en todo eso es es probable que tenga horrible rendimiento. ¿Tiene Hibernate algún truco en la manga para mantener este rendimiento relativamente bueno? ¿O cargar una referencia a una de estas clases por pkey va a tomar mucho tiempo?
Quizás quieras ver http://stackoverflow.com/questions/2700680/table-per-subclass-inheritance-relationship-how-to-query-against-the-parent-clas –
Por curiosidad, me pregunto si algunos otros sistemas de almacenamiento basados en objetos JPA tienen el mismo problema (es decir, ObjectDB). En otras palabras, tal vez una base de datos relacional estándar no sea la mejor, especialmente porque tiene un gran gráfico de objetos. –