Situación
Tengo una entidad con una DiscriminatorColumn
, configurado para la herencia simple tabla:DiscriminatorColumn como parte de la clave primaria/Identificación del
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class ContainerAssignment{
...
}
'ContainerAssignment' tiene una referencia a otra entidad:
@JoinColumn(name="CONTAINER_ID")
private Container container;
Un contenedor puede tener un ContainerAssignment
de cada TIPO. Esto significa que la clave principal de la tabla ContainerAssignment
está definida por CONTAINER_ID
y TYPE
.
ContainerAssignment
tiene algunas subclases, por ejemplo.
@Entity
@DiscriminatorValue("SOME_TYPE")
public class SomeTypeOfContainerAssignment extends ContainerAssignment{
...
}
Sólo habrá un solo SomeTypeOfContainerAssignment
ejemplo para un determinado CONTAINER_ID
.
Problema
Si defino la APP @Id
tan sólo el recipiente sobre la mesa ContainerAssignment, no puedo hacer entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
, que es grande. Esto ejecuta algo a lo largo de las líneas de SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1 AND TYPE = 'SOME_TYPE';
. Sabe que necesita la verificación TYPE aquí, debido a la anotación @DiscriminatorValue("SOME_TYPE")
en la entidad.
Sin embargo, esto significa que las referencias anteriores de Container a ContainerAssignment se rompen porque Container no es realmente la clave principal. Por ejemplo, si Container tiene @OneToOne(mappedBy=container) private SomeTypeOfContainerAssignment assignment;
, cuando lee en un contenedor, se leerá en la asignación por algo como SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1;
, sin la verificación de tipo. Esto le da todas las asignaciones para un contenedor, y luego elige uno aparentemente al azar, potencialmente del tipo incorrecto, en cuyo caso arroja una excepción.
Si, en cambio, defino el JPA @Id
de ContainerAssignment como un identificador compuesto utilizando contenedor y tipo, las referencias a las subclases de ContainerAssignment funcionan bien. No se puede hacer entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
, porque containerId no es la identificación Tengo que hacer entityManager.find(SomeTypeOfContainerAssignment.class, new MyPk(containerId, "SOME_TYPE"))
, que parece rechazar el punto de @DiscriminatorValue("SOME_TYPE")
. También podría usar una única Entidad de Asignación de Contenedor si tuviera que especificar el tipo en buscar de todos modos.
Pregunta
¿Hay una manera de tener referencias de trabajo a las subclases de una entidad única herencia de tablas donde la clave principal en la tabla es compuesta en la columna discriminadora y que también sea capaz de EntityManager.find
por sólo el parte (s) de la clave principal que no son el discriminador?
Gracias por su respuesta, pero realmente no resuelve la pregunta: ¿hay alguna manera de poner el 'DiscriminatorColumn' dentro del PK? Estoy de acuerdo en que una PK artificial es la mejor opción, pero en muchos sistemas no podemos controlar el esquema y tenemos que lidiar con PK compuestos. –
También observe que NUNCA usar claves primarias compuestas es un antipatrón, según el libro de Bill Karwin. – atorres