Beispiel: Container Managed N:M-Relationship zweiter Entity Beans (JBoss 4.0)


Inhalt:

Anlegen der Application
Anlegen der Entity Bean "KuchenNM"
Anlegen der Entity-Bean "ZutatNM"
Hinzufügen der Relationship
Anlegen des Webclients
Blick in die Datenbank

Beispiel für zwei Container Managed Entity Bean, auf die per Webclient zugegriffen wird. Zwischen den beiden Beans besteht eine Container Managed Relationship, der Primary Key ist Container-erzeugt.
Änderung im Vergleich zu den vorherigen Beispielen: Kuchen und Zutat werden im Webclient separat eingegeben, die n:m-Verknüpfung ist eine Zuordnung von Kuchen zu Zutat. Die Information "Menge" entfällt, da wir ansonsten die Relationship um weitere Fehler erweitern müßten und dafür wahrscheinlich eine eigene Zuordnungs-Bean nötig wäre.
Hier gibt es das Projekt zum Download (dies ist ein EAR-Export, die Importanleitung findet man im Stateless-Beispiel): KuchenZutatNM.ear
ACHTUNG: Nach dem Import XDoclet-Builder im EJB-Projekt aktivieren ! (Das Web-Projekt verfügt über keine Servlets, deshalb kann WebDoclet dort nicht verwendet werden)

Aufbau des Beispieles

a) Entity Bean-Klasse für Kuchen mit Local-Interfaces.
b) Entity Bean-Klasse für Zutat mit Local-Interfaces.
c) Webclient


Anlegen der Application

Ein "EAR Application Project" mit dem Namen "KuchenZutatNM" erstellen.
Zu erzeugende Module definieren. Dieses Beispiel benötigt ein EJB-Projekt und ein Anwendungsclientprojekt.
Erzeugen einer Application (Module)


Anlegen der Entity Bean "KuchenNM"

Wir legen eine Session Bean namens "KuchenNMBean" im Package "de.fhw.swtvertiefung.knauf.kuchenzutatnm" an.
KuchenNM Bean (1)
Im letzten Schritt ändern wir das zu implementierende Interface von "javax.ejb.SessionBean" auf "javax.ejb.EntityBean".
Kuchen Bean (2)


Den Rest der Arbeit müssen wir in der Bean-Klasse und mittels XDoclet erledigen.


Anlegen der Entity-Bean "ZutatNM"

Die ZutatNM-Bean sieht fast genauso aus wie die KuchenNM-Bean. Wir können Sie eigentlich durch Kopieren erzeugen. Zu beachten ist dass alle Referenzen in XDoclet-Tags angepaßt werden. Wir müssen die Property "name" in "zutatName" ändern.


Hinzufügen der Relationship

In "KuchenBean" fügen wir die folgenden beiden Methoden zu:
  /**Abrufen aller Zutaten dieses Kuchens.
   * @return Collection von Zutat-Objekten.
   * @ejb.interface-method view-type="local" 
   * @ejb.relation  
   *   name="KuchenZutaten"  
   *   role-name="kuchen-hat-zutaten" 
   * @jboss.relation fk-constraint="true"  
   *   related-pk-field="zutatid" 
   *   fk-column="zutat_fk" 
   */
  public abstract Collection getZutaten();

  /**Setzen der kompletten Zutaten-Liste des Kuchens.
   * Wird vom Container übernommen.
   * @param coll_Zutaten Liste der Zutaten.
   * 
   * @ejb.interface-method view-type="local" 
   */
  public abstract void setZutaten (Collection coll_Zutaten); 
Außerdem werden die drei Hilfsmethoden "addZutat", "removeZutat" und "getZutatenListe" zugefügt, alle sollen in das Local-Interface eingebaut werden.

In der Zutat-Bean wird getKuchen und setKuchen eingebaut. Hier wird die andere Seite der Relation deklariert:
  /**Abrufen der Kuchen, in denen diese Zutat verwendet wird.
   * @return Liste von Kuchen der Zutat.
   *
   * @ejb.interface-method view-type="local" 
   * @ejb.relation    
   *   name="KuchenZutaten"    
   *   role-name="zutat-hat-kuchen"   
   * @jboss.relation fk-constraint="true"  
   *   related-pk-field="kuchenid"  
   *   fk-column="kuchen_fk"  
   */
  public abstract Collection getKuchen();

  /**Setzen des Kuchens, zu dem die Zutat gehört.
   * @param collKuchen Liste von Kuchen die diese Zutat verwenden.
   * 
   * @ejb.interface-method view-type="local"  
   */
  public abstract void setKuchen(Collection collKuchen); 
Hierzu wichtig:
-Der Name der Relation (hier: "KuchenZutaten") muss auf beiden Seiten der Relation gleich sein.
-Auf beiden Seiten muss eine @jboss-relation deklariert werden, da der Server sonst eine Fehlermeldung ausspuckt. Mittels dieser JBoss-Relation geben wir an auf welches Primary-Key-Feld der KuchenBean sich die Relation "KuchenZutat" bezieht (wichtig: der Name dieses Felds ist im @jboss.unknown-pk-Tag deklariert) und wie das Feld in der referenzierten Tabelle heißen soll. Der Container fügt die Spalten aus dem Attribut fk-column in eine Tabelle ein, die er aus Bean-Namen und Rollen-Namen erstellt.

In "ejb-jar.xml" sieht das dann so aus:
   <relationships >
      <ejb-relation >
         <ejb-relation-name>KuchenZutaten</ejb-relation-name>

         <ejb-relationship-role >
            <ejb-relationship-role-name>kuchen-hat-zutaten</ejb-relationship-role-name>
            <multiplicity>Many</multiplicity>
            <relationship-role-source >
               <ejb-name>KuchenNM</ejb-name>
            </relationship-role-source>
            <cmr-field >
               <cmr-field-name>zutaten</cmr-field-name>
               <cmr-field-type>java.util.Collection</cmr-field-type>
            </cmr-field>
         </ejb-relationship-role>

         <ejb-relationship-role >
            <ejb-relationship-role-name>zutat-hat-kuchen</ejb-relationship-role-name>
            <multiplicity>Many</multiplicity>
            <relationship-role-source >
               <ejb-name>ZutatNM</ejb-name>
            </relationship-role-source>
            <cmr-field >
               <cmr-field-name>kuchen</cmr-field-name>
               <cmr-field-type>java.util.Collection</cmr-field-type>
            </cmr-field>
         </ejb-relationship-role>

      </ejb-relation>
   </relationships> 
"jboss-cmp.xml" sieht so aus:
  <relationships>
    <ejb-relation>
      <ejb-relation-name>KuchenZutaten</ejb-relation-name>
      <relation-table-mapping>
      </relation-table-mapping>

      <ejb-relationship-role>
          <ejb-relationship-role-name>kuchen-hat-zutaten</ejb-relationship-role-name>
          <fk-constraint>true</fk-constraint>
          <key-fields>
             <key-field>
               <field-name>kuchenid</field-name>
               <column-name>kuchen_fk</column-name>
             </key-field>
          </key-fields>

      </ejb-relationship-role>
      <ejb-relationship-role>
          <ejb-relationship-role-name>zutat-hat-kuchen</ejb-relationship-role-name>
          <fk-constraint>true</fk-constraint>
          <key-fields>
             <key-field>
               <field-name>zutatid</field-name>
               <column-name>zutat_fk</column-name>
             </key-field>
          </key-fields>

      </ejb-relationship-role>
    </ejb-relation>
  </relationships> 


Anlegen des Webclients

Der Webclient muss die EJB-JARs referenzieren. Dazu in die Eigenschaften des Webmoduls "KuchenZutatNMWeb" wechseln und unter "J2EE Module Depdencies" das EJB-JAR wählen.
EJB-Dependencies
EJB-Verweise festlegen:
Da wir hier kein Servlet verwenden können wir uns den EJB-Verweis nicht per XDoclet generieren lassen. Also in "web.xml" folgendes einfügen:
<ejb-local-ref>
	<ejb-ref-name>ejb/ZutatNM</ejb-ref-name>
	<ejb-ref-type>Entity</ejb-ref-type>
	<local-home>de.fhw.swtvertiefung.knauf.kuchenzutatnm.ZutatNMLocalHome</local-home>
	<local>de.fhw.swtvertiefung.knauf.kuchenzutatnm.ZutatNMLocal</local>
	<ejb-link>ZutatNM</ejb-link>
</ejb-local-ref>
<ejb-local-ref>
	<ejb-ref-name>ejb/KuchenNM</ejb-ref-name>
	<ejb-ref-type>Entity</ejb-ref-type>
	<local-home>de.fhw.swtvertiefung.knauf.kuchenzutatnm.KuchenNMLocalHome</local-home>
	<local>de.fhw.swtvertiefung.knauf.kuchenzutatnm.KuchenNMLocal</local>
	<ejb-link>KuchenNM</ejb-link>
</ejb-local-ref> 

Es müssen vier JSP-Seiten "index.jsp", "KuchenEdit.jsp", "ZutatEdit.jsp" und "KuchenZutaten.jsp" zugefügt werden.

Jetzt die Anwendung nur noch deployen. Sie ist unter
http://localhost:8080/KuchenZutatNMWeb/index.jsp zu erreichen.


Blick in die Datenbank

In der Datenbank sieht das so aus:
Mapping-Tabelle
Der Name der Mapping-Datenbank wurde erzeugt aus den Namen der beiden beteiligten Beans sowie den jeweiligen Rollen-Namen ("Zutaten" auf KuchenNM-Seite, "Kuchen" auf ZutatNM-Seite).


Version 1.0.0.1, Stand 24.11.2005
Historie:
1.0.0.0 (21.11.2005): Erstellt
1.0.0.1 (24.11.2005): Falscher Link zur Startseite der Anwendung