Beispiel: Entity Inheritance


Inhalt:

Strategie SINGLE_TABLE
Strategie TABLE_PER_CLASS
Strategie JOINED
Application Client
Troubleshooting
Ohne Annotations

Beispiel für eine Entity Bean die zwei Subklassen mit unterschiedlichen Feldern hat. Diese Vererbung wird mittels der drei im JavaEE5-Standard definierten Vererbungsstrategien abgebildet.
Hier gibt es nur einen sehr trivialen Application Client, der für jede der drei Strategien gleich abläuft: es wird eine Bean von jedem Subtyp erzeugt, diese Beans werden aus der DB geladen, am Schluss wird wieder alles gelöscht.
Hier gibt es das Projekt zum Download (dies ist ein EAR-Export, die Importanleitung findet man im Stateless-Beispiel): KuchenInheritance.ear

Aufbau des Beispieles

a) Entity Bean-Klasse sowie zwei Subklassen gemäß Strategie SINGLE_TABLE.
b) Entity Bean-Klasse sowie zwei Subklassen gemäß Strategie TABLE_PER_CLASS.
c) Entity Bean-Klasse sowie zwei Subklassen gemäß Strategie JOINED.
d) Application Client
Für alle drei Strategien sind die Beispiele identisch aufgebaut: es gibt eine (abstrakte) KuchenBaseBean mit den Attributen "id" und "name". Außerdem gibt es eine Subklasse KuchenKaeseBean für Beans mit der Spezialisierung "Käsekuchen" und dem zusätzlichen Attribut "mengeKaese", sowie eine Subklasse KuchenMohnBean für Beans mit der Spezialisierung "Mohnkuchen" und dem zusätzlichen Attribut "mengeMehl" und "mengeMohn" (ja, ich weiß: seeeehr sinnloses Beispiel ;-) ).
Im Code stecken die Beans in eigenen Packages, die gemäß Vererbungsstrategie benannt sind, außerdem enthält der Klassenname die Strategie.


Strategie SINGLE_TABLE

Dies bedeutet: es wird nur eine einzige Tabelle in der Datenbank erzeugt, die so heißt wie die Basisklasse und alle Felder aller Subklassen enthält. Zur Unterscheidung der einzelnen Beans wird eine "Discriminator Column" eingeführt, die pro Datensatz eine Kennung des Typs enthält.

Basisklasse KuchenSingleTableBaseBean:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@NamedQuery (name="findAllKuchenSingleTable", query="select o from KuchenSingleTableBaseBean o")
public abstract class KuchenSingleTableBaseBean implements Serializable
{
  private Integer intId;
  private String strName;
  
  public KuchenSingleTableBaseBean()
  { 
  }
  
  @Column()
  @Id ()
  @GeneratedValue ()
  public Integer getId()
  {
    return this.intId;
  }

  public void setId(Integer int_Id)
  {
    this.intId = int_Id;
  }
  
  @Column()
  public String getName()
  {
    return this.strName;
  }

  public void setName(String str_Name)
  {
    this.strName = str_Name;
  }
} 
Die Strategie wird über die Annotation @Inheritance definiert, als Typ haben wir hier InheritanceType.SINGLE_TABLE gewählt. Hier könnten Name und Typ der Discriminator Column über eine Annotation @DiscriminatorColumnangegeben werden, ich belasse das hier beim Default (resultiert in einer Spalte "DTYPE" in der Datenbank).
Die Named Query dient dazu alle Kuchen inklusive aller Subtypen zu laden, also den gesamten Tabelleninhalt.

Subklasse KuchenSingleTableKaeseBean:
@Entity
@DiscriminatorValue(value="kaesekuchen")
@NamedQuery (name="findAllKaeseKuchenSingleTable", query="select o from KuchenSingleTableKaeseBean o")
public class KuchenSingleTableKaeseBean extends KuchenSingleTableBaseBean implements Serializable
{
  private Integer intMengeKaese = 0;

  @Column
  public Integer getMengeKaese()
  {
    return this.intMengeKaese;
  }

  public void setMengeKaese(Integer _intMengeKaese)
  {
    this.intMengeKaese = _intMengeKaese;
  }
}
Hier wird zur Erkennung von Instanzen dieser Klasse in der Datenbank ein Wert der Discriminator Column mittels der Annotation @DiscriminatorValue eingetragen: alle Käsekuchen sollen hier den Wert "kaesekuchen" stehen haben.
Die Named Query liefert NUR Käsekuchen zurück, alle anderen Typen werden nicht berücksichtigt.

Ähnlich sieht es für die Subklasse KuchenSingleTableMohnBean aus (hier nur den Anfang der Klasse):
@Entity
@DiscriminatorValue(value="mohnkuchen")
@NamedQuery (name="findAllMohnKuchenSingleTable", query="select o from KuchenSingleTableMohnBean o")
public class KuchenSingleTableMohnBean extends KuchenSingleTableBaseBean implements Serializable
{
  ... 
Auch hier wird ein Discriminator Value gesetzt, und es wird eine spezielle Named Query deklariert die nur Mohnkuchen zurückliefert.

Das Ergebnis in der Datenbank sieht so aus:
SINGLE_TABLE


Strategie TABLE_PER_CLASS

Dies bedeutet: es wird pro echter Bean-Klasse (abstrakte Klassen ausgenommen !) eine Tabelle in der Datenbank erzeugt, und alle Felder der Subklasse sowie aller Parentklassen enthält.

Basisklasse KuchenTablePerClassBaseBean:
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@NamedQuery (name="findAllKuchenSingleTable", query="select o from KuchenTablePerClassBaseBean o")
public abstract class KuchenTablePerClassBaseBean implements Serializable
{
  private Integer intId;
  private String strName;
  
  public KuchenSingleTableBaseBean()
  { 
  }
  
  @Column()
  @Id ()
  @GeneratedValue (strategy=GenerationType.TABLE)
  public Integer getId()
  {
    return this.intId;
  }

  ...
} 
Der Rest des Codes ist identisch mit dem vorherigen Beispiel.

Besonderheit dieses Beispiels: Das automatische Generieren des Primary Keys muss hier die "strategy" explizit setzen. Der Default GenerationType.AUTO führt zu folgender Meldung:
javax.persistence.PersistenceException: org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassKaeseBean
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:720)
	at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:127)
	at org.jboss.ejb3.entity.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:246)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	....

Die beiden Subklassen KuchenTablePerClassKaeseBean und KuchenTablePerClassMohnBean unterscheiden sich nicht von den Beans aus dem vorherigen Beispiel (abgesehen davon dass hier die Annotation @DiscriminatorValue natürlich nicht verwendet werden darf und die Named Query einen anderen Namen hat).

Das Ergebnis in der Datenbank sieht so aus:
TABLE_PER_CLASS
Für die abstrakte Basisklasse KuchenTablePerClassBaseBean wurde keine Tabelle erzeugt weil diese abstrakt ist.

Eine Besonderheit ist, dass jetzt eine neue Tabelle namens "HIBERNATE_SEQUENCES" entsteht, über die die IDs erzeugt werden:
HIBERNATE_SEQUENCES
Der Wert in der Spalte "SEQUENCE_NEXT_HI_VALUE" ist allerdings nicht die nächste ID, der hat wohl eine andere Bedeutung


Strategie JOINED

Dies bedeutet: es wird pro Bean-Klasse (einschließlich abstrakter Klassen) eine Tabelle in der Datenbank erzeugt, die alle Felder der jeweiligen Klasse enthält.

Basisklasse KuchenJoinedBaseBean:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@NamedQuery (name="findAllKuchenJoined", query="select o from KuchenJoinedBaseBean o")
public abstract class KuchenJoinedBaseBean implements Serializable
{
  ...
} 
Der Rest des Codes ist identisch mit dem Beispiel "SINGLE_TABLE" (einschließlich automatisch generierter ID).

Die beiden Subklassen KuchenJoinedKaeseBean und KuchenJoinedMohnBean unterscheiden sich nicht von den Beans aus dem vorherigen Beispiel (abgesehen davon dass hier die Annotation @DiscriminatorValue natürlich nicht verwendet werden darf und die Named Query einen anderen Namen hat).

Das Ergebnis in der Datenbank sieht so aus:
JOINED


Application Client

Der Client besteht aus drei Methoden die jeweils einen Kuchen von jedem Typ erzeugen, ihn speichern, danach die Liste aller Kuchen sowie die Listen der Mohn- und der Käsekuchen abrufen sowie die beiden Kuchen wieder löschen.
Im folgenden der Code für die Strategie "SINGLE_TABLE":
private static void testSingleTable(InitialContext _initialContext) throws NamingException
  {
    Object objKuchenWorker = _initialContext.lookup("java:comp/env/ejb/KuchenSingleTableWorker");
    KuchenSingleTableWorker kuchenWorker = (KuchenSingleTableWorker) PortableRemoteObject.narrow(objKuchenWorker, KuchenSingleTableWorker.class);
    
    KuchenSingleTableKaeseBean kaeseKuchen = new KuchenSingleTableKaeseBean();
    kaeseKuchen.setName("Käsekuchen 1");
    kaeseKuchen.setMengeKaese(100);
    
    kaeseKuchen = (KuchenSingleTableKaeseBean) kuchenWorker.saveKuchen(kaeseKuchen);
    
    KuchenSingleTableMohnBean mohnKuchen = new KuchenSingleTableMohnBean();
    mohnKuchen.setName("Mohnkuchen 1");
    mohnKuchen.setMengeMohn(50);
    mohnKuchen.setMengeMehl(300);
    
    mohnKuchen = (KuchenSingleTableMohnBean) kuchenWorker.saveKuchen(mohnKuchen); 
    
    //Alle Kuchen ausgeben:
    System.out.println ("================================");
    System.out.println ("Single Table");
    System.out.println ("==>Alle Kuchen holen:");
    List<KuchenSingleTableBaseBean> listKuchenBase = kuchenWorker.getKuchen();
    for (KuchenSingleTableBaseBean kuchenAktuell : listKuchenBase)
    {
      System.out.println ("   -" + kuchenAktuell.getName());
    }
    
    System.out.println ("==>Käsekuchen holen:");
    List<KuchenSingleTableKaeseBean> listKuchenKaese = kuchenWorker.getKaeseKuchen();
    for (KuchenSingleTableKaeseBean kuchenAktuell : listKuchenKaese)
    {
      System.out.println ("   -" + kuchenAktuell.getName());
    }
    
    System.out.println ("==>Mohnkuchen holen:");
    List<KuchenSingleTableMohnBean> listKuchenMohn = kuchenWorker.getMohnKuchen();
    for (KuchenSingleTableMohnBean kuchenAktuell : listKuchenMohn)
    {
      System.out.println ("   -" + kuchenAktuell.getName());
    }
    
    //Aufräumen:
    kuchenWorker.deleteKuchen(mohnKuchen);
    kuchenWorker.deleteKuchen(kaeseKuchen);
    System.out.println ("==>Alle Kuchen gelöscht !");
  } 
Der Code für die Strategie "JOINED" und "TABLE_PER_CLASS" ist bis auf die geänderten Klassennamen identisch.


Troubleshooting

Wenn eine Bean aus der Vererbungshierarchie als Value Object zu Clients geschickt werden soll, dann ist es wichtig, dass alle Klassen der Vererbungshierarchie das Interface java.io.Serializable implementieren. Fehlt es bei einer Klasse, dann werden deren Felder nicht serialisiert, wohl aber die Felder aller anderen Klassen aus der Vererbungshierarchie, die java.io.Serializable implementieren !


Ohne Annotations

"ejb-jar.xml" sieht so aus:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                           http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
	<display-name>
	KuchenInheritanceEJB</display-name>
	
	<enterprise-beans>
		<session>
			<description>
				<![CDATA[Stateless Session Bean für das Arbeiten mit Kuchen gemäß Joined-Strategie]]>
			</description>
			<display-name>KuchenJoinedWorkerBean</display-name>
			<ejb-name>KuchenJoinedWorkerBean</ejb-name>
			<remote>de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedWorker</remote>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedWorkerBean</ejb-class>
			<session-type>Stateless</session-type>
			<persistence-context-ref>
				<persistence-context-ref-name>KuchenInheritancePersistenceUnitRef</persistence-context-ref-name>
				<persistence-unit-name>kuchenInheritancePersistenceUnit</persistence-unit-name>
				<injection-target>
					<injection-target-class>
						de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedWorkerBean
					</injection-target-class>
					<injection-target-name>entityManager</injection-target-name>
				</injection-target>
			</persistence-context-ref>
		</session>
		<session>
			<description>
				<![CDATA[Stateless Session Bean für das Arbeiten mit Kuchen gemäß SingleTable-Strategie]]>
			</description>
			<display-name>KuchenSingleTableWorkerBean</display-name>
			<ejb-name>KuchenSingleTableWorkerBean</ejb-name>
			<remote>de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableWorker</remote>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableWorkerBean</ejb-class>
			<session-type>Stateless</session-type>
			<persistence-context-ref>
				<persistence-context-ref-name>KuchenInheritancePersistenceUnitRef</persistence-context-ref-name>
				<persistence-unit-name>kuchenInheritancePersistenceUnit</persistence-unit-name>
				<injection-target>
					<injection-target-class>
						de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableWorkerBean
					</injection-target-class>
					<injection-target-name>entityManager</injection-target-name>
				</injection-target>
			</persistence-context-ref>
		</session>
		
		<session>
			<description>
				<![CDATA[Stateless Session Bean für das Arbeiten mit Kuchen TablePerClass-Strategie]]>
			</description>
			<display-name>KuchenTablePerClassWorkerBean</display-name>
			<ejb-name>KuchenTablePerClassWorkerBean</ejb-name>
			<remote>de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassWorker</remote>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassWorkerBean</ejb-class>
			<session-type>Stateless</session-type>
			<persistence-context-ref>
				<persistence-context-ref-name>KuchenInheritancePersistenceUnitRef</persistence-context-ref-name>
				<persistence-unit-name>kuchenInheritancePersistenceUnit</persistence-unit-name>
				<injection-target>
					<injection-target-class>
						de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassWorkerBean
					</injection-target-class>
					<injection-target-name>entityManager</injection-target-name>
				</injection-target>
			</persistence-context-ref>
		</session>
		
		<entity>
			<description>
				<![CDATA[Basis-Entity Bean für einen Kuchen gemäß JOINED-Strategie.]]>
			</description>
			<display-name>KuchenJoinedBaseBean</display-name>
			<ejb-name>KuchenJoinedBaseBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedBaseBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		<entity>
			<description>
				<![CDATA[Sub-Entity Bean für einen Käse-Kuchen gemäß JOINED-Strategie.]]>
			</description>
			<display-name>KuchenJoinedKaeseBean</display-name>
			<ejb-name>KuchenJoinedKaeseBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedKaeseBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		<entity>
			<description>
				<![CDATA[Sub-Entity Bean für einen Käse-Kuchen gemäß JOINED-Strategie.]]>
			</description>
			<display-name>KuchenJoinedMohnBean</display-name>
			<ejb-name>KuchenJoinedMohnBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedMohnBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		
		<entity>
			<description>
				<![CDATA[Basis-Entity Bean für einen Kuchen gemäß SINGLE_TABLE-Strategie.]]>
			</description>
			<display-name>KuchenSingleTableBaseBean</display-name>
			<ejb-name>KuchenSingleTableBaseBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableBaseBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		<entity>
			<description>
				<![CDATA[Sub-Entity Bean für einen Käse-Kuchen gemäß SINGLE_TABLE-Strategie.]]>
			</description>
			<display-name>KuchenSingleTableKaeseBean</display-name>
			<ejb-name>KuchenSingleTableKaeseBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableKaeseBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		<entity>
			<description>
				<![CDATA[Sub-Entity Bean für einen Käse-Kuchen gemäß SINGLE_TABLE-Strategie.]]>
			</description>
			<display-name>KuchenSingleTableMohnBean</display-name>
			<ejb-name>KuchenSingleTableMohnBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableMohnBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		
		<entity>
			<description>
				<![CDATA[Basis-Entity Bean für einen Kuchen gemäß TABLE_PER_CLASS-Strategie.]]>
			</description>
			<display-name>KuchenTablePerClassBaseBean</display-name>
			<ejb-name>KuchenTablePerClassBaseBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassBaseBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		<entity>
			<description>
				<![CDATA[Sub-Entity Bean für einen Käse-Kuchen gemäß TABLE_PER_CLASS-Strategie.]]>
			</description>
			<display-name>KuchenTablePerClassKaeseBean</display-name>
			<ejb-name>KuchenTablePerClassKaeseBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassKaeseBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
		<entity>
			<description>
				<![CDATA[Sub-Entity Bean für einen Käse-Kuchen gemäß TABLE_PER_CLASS-Strategie.]]>
			</description>
			<display-name>KuchenTablePerClassMohnBean</display-name>
			<ejb-name>KuchenTablePerClassMohnBean</ejb-name>
			<ejb-class>de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassMohnBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>java.lang.Integer</prim-key-class>
			<reentrant>false</reentrant>
		</entity>
	</enterprise-beans>
</ejb-jar> 
Es gibt keine Neuerungen im Vergleich zum KuchenZutatNM-Beispiel.

"orm.xml" enthält die Angaben über das Mapping:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
	version="1.0">
	<named-query name="findAllKuchenJoined">
		<query>select o from KuchenJoinedBaseBean o</query>
	</named-query>
	<named-query name="findAllKaeseKuchenJoined">
		<query>select o from KuchenJoinedKaeseBean o</query>
	</named-query>
	<named-query name="findAllMohnKuchenJoined">
		<query>select o from KuchenJoinedMohnBean o</query>
	</named-query>
	
	<named-query name="findAllKuchenSingleTable">
		<query>select o from KuchenSingleTableBaseBean o</query>
	</named-query>
	<named-query name="findAllKaeseKuchenSingleTable">
		<query>select o from KuchenSingleTableKaeseBean o</query>
	</named-query>
	<named-query name="findAllMohnKuchenSingleTable">
		<query>select o from KuchenSingleTableMohnBean o</query>
	</named-query>
	
	<named-query name="findAllKuchenTablePerClass">
		<query>select o from KuchenTablePerClassBaseBean o</query>
	</named-query>
	<named-query name="findAllKaeseKuchenTablePerClass">
		<query>select o from KuchenTablePerClassKaeseBean o</query>
	</named-query>
	<named-query name="findAllMohnKuchenTablePerClass">
		<query>select o from KuchenTablePerClassMohnBean o</query>
	</named-query>
	
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedBaseBean" access="PROPERTY"
		metadata-complete="true">
		<inheritance strategy="JOINED"/>
		<attributes>
			<id name="id">
				<column name="ID" />
				<generated-value />
			</id>
			<basic name="name">
				<column name="NAME" />
			</basic>
		</attributes>
	</entity>
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedKaeseBean" access="PROPERTY"
		metadata-complete="true">
		<attributes>
			<basic name="mengeKaese">
				<column name="MENGEKAESE" />
			</basic>
		</attributes>
	</entity>
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.joined.KuchenJoinedMohnBean" access="PROPERTY"
		metadata-complete="true">
		<attributes>
			<basic name="mengeMohn">
				<column name="MENGEMOHN" />
			</basic>
			<basic name="mengeMehl">
				<column name="MENGEMEHL" />
			</basic>
		</attributes>
	</entity>
	
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableBaseBean" access="PROPERTY"
		metadata-complete="true">
		<inheritance strategy="SINGLE_TABLE"/>
		<attributes>
			<id name="id">
				<column name="ID" />
				<generated-value />
			</id>
			<basic name="name">
				<column name="NAME" />
			</basic>
		</attributes>
	</entity>
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableKaeseBean" access="PROPERTY"
		metadata-complete="true">
		<discriminator-value>kaesekuchen</discriminator-value>
		<attributes>
			<basic name="mengeKaese">
				<column name="MENGEKAESE" />
			</basic>
		</attributes>
	</entity>
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.singletable.KuchenSingleTableMohnBean" access="PROPERTY"
		metadata-complete="true">
		<discriminator-value>mohnkuchen</discriminator-value>
		<attributes>
			<basic name="mengeMohn">
				<column name="MENGEMOHN" />
			</basic>
			<basic name="mengeMehl">
				<column name="MENGEMEHL" />
			</basic>
		</attributes>
	</entity>
	
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassBaseBean" access="PROPERTY"
		metadata-complete="true">
		<inheritance strategy="TABLE_PER_CLASS"/>
		<attributes>
			<id name="id">
				<column name="ID" />
				<!-- Hier MUSS explizit eine strategy angegeben werden ! -->
				<generated-value strategy="TABLE"/>
			</id>
			<basic name="name">
				<column name="NAME" />
			</basic>
		</attributes>
	</entity>
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassKaeseBean" access="PROPERTY"
		metadata-complete="true">
		<attributes>
			<basic name="mengeKaese">
				<column name="MENGEKAESE" />
			</basic>
		</attributes>
	</entity>
	<entity class="de.fhw.swtvertiefung.knauf.kucheninheritance.tableperclass.KuchenTablePerClassMohnBean" access="PROPERTY"
		metadata-complete="true">
		<attributes>
			<basic name="mengeMohn">
				<column name="MENGEMOHN" />
			</basic>
			<basic name="mengeMehl">
				<column name="MENGEMEHL" />
			</basic>
		</attributes>
	</entity>

</entity-mappings>
Fett markiert sind hier neuen Elemente, die die Inheritance Strategy steuern. Auch hier ist bei Verwendung von "TABLE_PER_CLASS" die explizite Angabe der strategy nötig.

Die modifizierte Version des Projekts gibt es hier:
KuchenInheritanceNoAnnotation.ear.
ACHTUNG: Dieses Projekt kann nicht neben dem obigen KuchenInheritance-Beispiel existieren !



Stand 20.12.2007
Historie:
12.11.2007: Beispiel aus Vorjahresbeispiel erstellt, Anpassung an WTP 2.0. Auch bei TABLE_PER_CLASS ist jetzt ein autogenerierter PK möglich.
20.12.2007: Mini-Abschnitt "Troubleshooting"