Situation
Ich habe eine Entität mit einem DiscriminatorColumn
, für einzelne Tabelle Vererbung konfiguriert:DiscriminatorColumn als Teil des Primärschlüssels/id
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class ContainerAssignment{
...
}
'ContainerAssignment' hat einen Verweis auf eine andere Entität:
@JoinColumn(name="CONTAINER_ID")
private Container container;
Ein Container kann einen ContainerAssignment
von jedem TYPE haben. Dies bedeutet, dass der Primärschlüssel der Tabelle ContainerAssignment
durch die CONTAINER_ID
und die TYPE
definiert ist.
ContainerAssignment
hat einige Unterklassen, z.B.
@Entity
@DiscriminatorValue("SOME_TYPE")
public class SomeTypeOfContainerAssignment extends ContainerAssignment{
...
}
Es wird nur eine einzige SomeTypeOfContainerAssignment
Instanz für ein bestimmtes CONTAINER_ID
sein.
Problem
Wenn ich die JPA @Id
als nur die Container auf der ContainerAssignment Tabelle definieren, kann ich entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
tun, was toll ist. Dies läuft etwas in Richtung SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1 AND TYPE = 'SOME_TYPE';
. Es weiß, dass es die TYPE-Überprüfung hier wegen der @DiscriminatorValue("SOME_TYPE")
Annotation auf der Entität benötigt.
Dies bedeutet jedoch, dass die Rückverweise von Container auf ContainerAssignment abbrechen, da Container nicht wirklich der Primärschlüssel ist. Zum Beispiel, wenn Container eine @OneToOne(mappedBy=container) private SomeTypeOfContainerAssignment assignment;
hat, wenn Sie in einem Container lesen, wird es in der Zuordnung von etwas wie SELECT * FROM CONTAINER_ASSIGNMENT WHERE CONTAINER_ID = 1;
, ohne die Typprüfung lesen. Dies gibt ihm alle Zuweisungen für einen Container, und dann wählt er einen scheinbar zufällig aus, möglicherweise vom falschen Typ, in welchem Fall er eine Ausnahme auslöst.
Wenn ich stattdessen die JPA @Id
von ContainerAssignment als eine Composite-ID mit Container und Typ definieren, funktionieren die Verweise auf die Unterklassen von ContainerAssignment gut.
Allerdings kann ich entityManager.find(SomeTypeOfContainerAssignment.class, containerId)
nicht tun, weil ContainerId nicht die ID ist. Ich muss entityManager.find(SomeTypeOfContainerAssignment.class, new MyPk(containerId, "SOME_TYPE"))
tun, die den Punkt @DiscriminatorValue("SOME_TYPE")
zu besiegen scheint. Ich könnte auch nur eine einzige ContainerAssignment Entity verwenden, wenn ich den Typ bei der Suche trotzdem angeben muss.
Frage
Gibt es eine Möglichkeit Arbeits Verweise auf Unterklassen von einer einzigen Tabelle Vererbung Entity zu haben, wo der Primärschlüssel auf dem Tisch auf dem Diskriminator Spalte Verbund ist, während auch EntityManager.find
nur um in der Lage, das Teil (e) des Primärschlüssels, die nicht der Diskriminator sind?
Danke für Ihre Antwort, aber es löst nicht wirklich die Frage - gibt es eine Möglichkeit, die 'DiscriminatorColumn' in den PK einzubauen? Ich stimme zu, dass eine künstliche PK die beste Wahl ist, aber in vielen Systemen können wir das Schema nicht kontrollieren und müssen mit zusammengesetzten PKs umgehen. –
Beachten Sie auch, dass die Verwendung von zusammengesetzten Primärschlüsseln NIE ein Anti-Muster ist, laut Bill Karwin Buch. – atorres