EJB 3.0 many-to-many

Status
Nicht offen für weitere Antworten.

didiator

Mitglied
Hallo liebe Freunde,

ich muss gerade eine Aufgabe lösen, bei der ich entweder noch nicht die richtige Literatur gefunden habe oder mich nicht klug genug anstelle.

Es geht um die Realisierung eines many-to-many zugriffs über eine vorhandene Verbindungstabelle:


Tabelle Person
personID(PK)
Name
Vorname
...


Tabelle PersonAdr
ID(PK)
personID(FK)
adressid(FK)
adrTypID(FK)
emailID(FK)
...

Tabelle Adresse
adressid(PK)
Ort
PLZ
Strasse
HausNr
...


Die Verbindungstabelle enthält außer den beiden FKs weitere FKs auf andere Tabellen, ist also nicht die Standardimplementierung "Person_Adresse".

Ich will nun in der EJB Person eine Liste List<Adresse> adressen mit den vorhandenen Adressen haben. Dazu habe ich folgendes codiert:

Klasse "Person"
...
Code:
    @ManyToMany
    private List<Adresse> adressen;


    @JoinTable(name="PERSONADR",
        joinColumns=@JoinColumn(name="personID", referencedColumnName="personID"),
        inverseJoinColumns=@JoinColumn(name="adressid", referencedColumnName="adressid")
    )
    
    public List<Adresse> getAdressen()
    {
        return adressen;
    }

    public void setAdressen(List<Adresse> adressen)
    {
        this.adressen = adressen;
    }

    public void addAdresse(Adresse toAdd)
    {
        this.getAdressen().add(toAdd);
    }

    public void dropAdresse(Adresse toDrop)
    {
        this.getAdressen().remove(toDrop);
    }

Kernpunkt soll hier die @JoinTable - Annotation sein. Sie verweist nicht auf die Tabelle "Person_Adresse" als Standard (darüber würde es funktionieren), sondern auf die spezielle, schon vorhandene Verknüpfungstabelle. In joinColumns und inverseJoinColumns werden die passenden PKs und FKs angegeben.

Klasse "Adresse"

...

Code:
    @ManyToMany
    List<Person> personen;


Wenn ich die Applikation starte, bleibt die Liste mit den Adressen leer. Zur Kontrolle habe ich ein SQL Statement geschrieben und geprüft, ob die Tabelleninhalte richtig sind. Das war OK.

Wo ist hier mein Denkfehler?

Frage: Brauche ich eine EJB "PersonAdr"? Wenn ich über den Standard "Person_Adresse" war das nicht nötig?

Frage: Wann wird denn aus der Verbindungstabelle ausgewertet? Ich rufe derzeit aus einem Servlet getAdressen() auf. Reicht das aus?

Warum ist meine Liste List<Adresse> adressen leer?
 
G

Guest

Gast
Vermische nicht Anotationen an Attributen mit denen an Methoden. Etweder das eine oder das andere, nie gemischt.
 

didiator

Mitglied
Hallo Gast,

vielen Dank für Deinen Hinweis. Leider kann ich Dir aber nicht folgen. Was meinst Du ist denn hier vermischt?
 

semi

Top Contributor
Das hier war gemeint. Anotationen am Attribut und am Getter
Code:
@ManyToMany
private List<Adresse> adressen;

@JoinTable(name="PERSONADR",
    joinColumns=@JoinColumn(name="personID", referencedColumnName="personID"),
    inverseJoinColumns=@JoinColumn(name="adressid", referencedColumnName="adressid")
)
public List<Adresse> getAdressen()
{
    return adressen;
}
...

Du hast zwei Möglichkeiten. Direkt ein ManyToMany oder ein OneToMany mit einer Entity PersonAdresse.
Ich würde an deiner Stelle die zweite Variante vorziehen, da deine Zwischentabelle bereits einen PK hat
und noch paar zusätzliche FKs. Beachte aber, dass du dich um das Speichern von PersonAdresse selbst
kümmern musst.

Hier beide Varianten in einem (passend zu deinen Tabellen)
Code:
@Entity
public class Person
{
   @Id
   @GeneratedValue
   @Column(name = "PERSONID")
   private Long id;

   @ManyToMany
   @JoinTable(name = "PERSONADR", 
      joinColumns = { @JoinColumn(name = "PERSONID") }, 
      inverseJoinColumns = { @JoinColumn(name = "ADRESSID") }
   )
   private Set<Adresse> adressen;

   @OneToMany(mappedBy = "person")
   private Set<PersonAdresse> adressen2;

   ...
}

@Entity
public class Adresse
{
   @Id
   @GeneratedValue
   @Column(name = "ADRESSID")
   private Long id;

   @ManyToMany(mappedBy = "adressen")
   private Set<Person> personen;

   @OneToMany(mappedBy = "adresse")
   private Set<PersonAdresse> personen2;

   ...
}

@Entity
@Table(name = "PERSONADR")
public class PersonAdresse
{
   @Id
   @GeneratedValue
   private Long id;

   @ManyToOne
   @JoinColumn(name = "PERSONID")
   private Person person;

   @ManyToOne
   @JoinColumn(name = "ADRESSID")
   private Adresse adresse;

   ...
}

Übrigens, Sun emfiehlt Annotationen an Methoden bzw. an Gettern. Ich ziehe es immer vor diese an
den Attributen zu verwenden, da ich Getter und Setter selektiv verwende (z.B. kein Setter bei Id)
und Annotationen an Attributen für übersichtlicher halte. Man hat das ganze Lametta an einem Haufen.
Nicht jedes Feld braucht einen Getter oder Setter (oder auch nicht jedes Feld darf dies haben).
Bei Collections empfiehlt sich sowieso entsprechende Methoden anzubieten, um die Collections zu
manipulieren. Insbesondere das Ersetzen von Collections über einen Setter kann bei JPA lustige Effekte
hervorrufen. ;)

Mach den Setter auf jeden Fall weg
Code:
public void setAdressen(List<Adresse> adressen) 
{ 
   this.adressen = adressen; // damit ersetzt du die Collection, die von der JPA Implementierung gemanaged wird!
}
 

didiator

Mitglied
Hallo semi,

vielen Dank für Deine Auskünfte. Ich denke, damit kann ich etwas anfangen. Ich hatte mir zwischenzeitlich auch schon die Gedanken gemacht, das Problem in zwei one-to-many Beziehungen aufzulösen. Many-to-many wäre nämlich auch inhaltlich falsch. In dem Moment, wo die Vernnüpfungstabelle mehr als nur zwei Fremdschlüssen enthält, wäre eine Verknüpfung des dritten Schlüssels nämlich ein inhaltlicher Verstoß.
Beispiel: Eine Person hat beliebig viele Adressen, an einer Adresse könne beleibig viele Personen wohnen. Das wäre OK. Kommt aber jetzt z.B. noch eine Telefonnummer hinzu, stimmen die Aussagen nicht mehr, da die Telefonnummer dann nur der Adresse o.u. zuzuordnen ist. Man bekäne dann nicht mehr das gewünschte Ergebnis heraus wenn die Verknüpfung alle Telefonnummern liefern würde.
Deshalb muss man das wohl über eine eigene busines logic abwickeln.

Also, vielen Dank noch mal.


didiator
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben