# XML - bidirektionale Beziehungen



## nielson123 (16. Dez 2010)

Hallo,

ich habe eine Klasse Mannschaft und eine Klasse Spieler. Wenn ich nun das Ganze mit JAXB annotiere entsteht eine Endlosschleife, da die Mannschaft die Spieler referenzieren und die Spieler wieder die Mannschaft, ....Wie löse ich dieses Problem?


```
@XmlRootElement
public class Mannschaft{
 private private List<Spieler> Spieler
}

@XmlType(name = "spieler")
public class Spieler{
 private Mannschaft mannschaft
}
```


----------



## musiKk (16. Dez 2010)

Es gibt mehrere Möglichkeiten. Du könntest z. B. eine der beiden Richtungen beim Marshalling weglassen (etwa die Verbindung Spieler->Mannschaft) und in einer Klasse, die Kenntnis von beiden Klassen hat, ein Callback definieren, welches diese Verbindung im Nachhinein herstellt. Etwa so:

```
public class Mannschaft {
	void afterUnmarshal(Unmarshaller u, Object parent) {
		for(Spieler s : spieler) {
			s.setMannschaft(this);
		}
	}
}
```

Eine andere Möglichkeit wäre, XML-IDs zu verwenden. Das muss ein eindeutiger String sein - z. B. der Mannschaftsname - welcher dann referenziert werden kann:

```
public class Mannschaft {
	@XmlID
	private String name;
	
	private List<Spieler> spieler;
}

public class Spieler {
	@XmlIDREF
	private Mannschaft mannschaft;
}
```


----------



## nielson123 (16. Dez 2010)

Schonmal vielen Dank für die Antwort.

Gibt es auch eine Möglichkeit, wenn man einen eindeutigen Long-Wert hat?


----------



## Wildcard (16. Dez 2010)

Nimm doch EMF, damit geht das out-of-the-box und EMF ist JaxB auch in so ziemlich allen anderen Punkten überlegen.
In EMF markierst du die Referenz auf Spieler in Mannschaft als Containment, die Mannschaft 'besitzt' also den Spieler.
Die Referenz von Spieler auf Mannschaft ist eine Container Referenz, also das Opposite der anderen Referenz.
EMF sorgt dann auch automatisch dafür das sich die Referenz die ein Spieler auf seine Mannschaft hat automatisch ändert wenn du den Spieler einer anderen Mannschaft hinzufügst, dein Objekt Modell hält sich also automatisch konsistent, weil dein Spieler nur in einer Mannschaft gleichzeitig spielen kann.


----------



## nielson123 (19. Dez 2010)

Hi,

ich benutze jetzt doch Jaxb und bin noch auf ein Problem gestoßen. Ich würde gerne diese beiden Variablen in Mannschaft benutzen, wie annotiere ich das, das ich beim Test nicht immer einen fehler bekomme.

```
protected Map<String, Spieler> spieler = null;
protected String name = null;
```


```
@XmlElement(name = "spieler")
	@XmlElementWrapper(name = "allespieler")
	public Collection<Spieler> getSpieler() {
		return spieler.values();
	}
```


```
public void setSpieler(Collection<Spieler> spieler) {
		
		
		if (this.spieler == null) {
			this.spieler = new HashMap<String, Spieler>();
		} 
		else {
			this.spieler.clear();
		}
	
		for (Spieler s : spieler) {
			this.spieler.put(s.getname(), s);
		}
		
	}
```


----------



## musiKk (19. Dez 2010)

Maps sind die größte Schwachstelle von JAXB. Schau am besten mal bei Google, dazu muss man einen eigenen Adapter schreiben (Stichwörter [c]XmlAdapter[/c] und [c]XmlJavaTypeAdapter[/c]).


----------



## nielson123 (19. Dez 2010)

Ok, verstehe ich das richtig, dass ich von einer Map auf eine Collection(z.B. HashSet) adaptieren muss. Ich bin mir da nicht ganz sicher, da ich ja im getter eine Collection zurückbekomme und im Setter eine Collection übergebe und keine Map.

Übrigens vielen Dank für die schnellen Antworten.


----------



## Wildcard (20. Dez 2010)

EMF unterstützt übrigens Maps...


----------

