# JPA Entities und deren Beziehungen modellieren



## distortion85 (31. Okt 2015)

Hi zusammen,

ich möchte mal nach einer Hilfestellungzur Modellierung meiner JPA-Entitäten und deren Beziehungen untereinander fragen. Ich verwende als Klassennamen in meinem Projekt abstraktere Klassennamen, sodass ich das mal auf ein "besser greifbares" Beispiel ummünze.

Ich gehe von einem Festival aus, auf dem mehrere Auftritte stattfinden. Jeder Auftritt ist dabei natürlich genau einem Festival zuzuordnen. Bei einem Auftritt werden mehrere Instrumente gespielt, dabei ist jedes Instrument einzigartig und genau einem Auftritt zuzuordnen. Ein Instrument wird nur von einem Musiker gespielt und ein Musiker spielt nur genau ein Instrument. Im Relationenmodell sehen die Beziehungen nun also so aus:







Die Klassen haben folgende JPA-Annotationen:


```
@Entity
public class Veranstaltung implements Serializable {
..
@OneToMany(mappedBy = "veranstaltung", cascade = CascadeType.ALL)
    private List<Auftritt> auftritte;
..
}

@Entity
public class Auftritt implements Serializable {
..
@ManyToOne
    private Veranstaltung veranstaltung;
@OneToMany(mappedBy = "auftritt", cascade = CascadeType.ALL)
    private List<Instrument> instrumente;
..
}

@Entity
public class Instrument implements Serializable {
..
@ManyToOne(cascade = CascadeType.PERSIST)
    private Auftritt auftritt;
..
}
```

Das ganze habe ich mit einer REST-Schnittstelle versehen, die mir testweise angelegte Datenbankeinträge als JSON zurückliefert. 

Problem 1: Bei der Beziehung zwischen Instrument<-->Musiker bin ich unsicher, ob 1:n oder 1:1, da bestimmte Musiker in anderen Auftritten auch andere Instrumente spielen.
Problem 2: Ich kann eine Veranstaltung wunderbar abfragen und sehe, welche Auftritte dazu gehören. Aber sobald ich einen bestimmten Auftritt abfrage, ist dort keine Information darüber, zu welcher Veranstaltung dieser gehört. Genau so verhält es sich mit Auftritte<-->Instrumente. Frage ich einen Auftritt ab, sehe ich welche Instrumente gespielt werden. Frage ich aber ein Instrument ab, sehe ich nicht,zu welchem konkreten Auftritt es gehört...dabei habe ich die Beziehungen ja bidirektional umgesetzt. 

Nach JPA-Spezifikation ist die Many-Seite der Owner und die One-Seite die inverse Seite. Hier besteht das Problem also dabei, dass die Abfrage der Owner-Seite nicht die gewünschten Informationen liefert. Hoffe ist verständlich, ansonsten muss ich noch etwas mehr Code posten...
Gedankliche Hinweise?

Grüße


----------



## stg (1. Nov 2015)

distortion85 hat gesagt.:


> Problem 1: Bei der Beziehung zwischen Instrument<-->Musiker bin ich unsicher, ob 1:n oder 1:1, da bestimmte Musiker in anderen Auftritten auch andere Instrumente spielen.


Welcher Musiker welches Instrument spielt hängt also davon ab, welchen Auftritt man betrachtet. Denkbar wäre also zum Beispiel eine weitere Enttiy "Spielt", in welcher du Instrument und Musiker abspeicherst. In der Entity "Auftritt" hast du dann eine Liste dieser "Spielt"-Einträge. Das ist jetzt nicht zu Ende gedacht, ob es wirklich genau deine Anforderungen abdeckt. Ich will nur darauf hinaus, dass du, um solche Beziehungen korrekt abzubilden, oft auf solcherlei "Hilfstabellen" zurückgreifen musst.



> Problem 2: Ich kann eine Veranstaltung wunderbar abfragen und sehe, welche Auftritte dazu gehören. Aber sobald ich einen bestimmten Auftritt abfrage, ist dort keine Information darüber, zu welcher Veranstaltung dieser gehört. Genau so verhält es sich mit Auftritte<-->Instrumente. Frage ich einen Auftritt ab, sehe ich welche Instrumente gespielt werden. Frage ich aber ein Instrument ab, sehe ich nicht,zu welchem konkreten Auftritt es gehört...dabei habe ich die Beziehungen ja bidirektional umgesetzt.


Das ist aber ein grundsätzliches XML- bzw JSON-Problem bei bidirektionalen Beziehungen. Wenn du das XML/JSON automatisch generieren lässt, dann steckst du, sofern du nicht eine Richtung "weglässt" sofort in einer endlosen Rekursion fest. Je nach Anforderung kannst du aber (bei den großen bekannten APIs wie JAXB) das Standard-Verhalten überschreiben und die "andere Richtung" deines Mappings abbilden. Oder du schreibst dir da selbst was, um dein XML / JSON zu generieren.


----------



## distortion85 (1. Nov 2015)

> Das ist aber ein grundsätzliches XML- bzw JSON-Problem bei bidirektionalen Beziehungen.


Das ist interessant. Das Problem mit der Rekursion ist mir begegnet und ich hatte es mit den den Annotiationen *@JsonManagedReference* bzw *@JsonBackReference *unterbunden.



> bei den großen bekannten APIs wie JAXB


Ich benutze derzeit Jackson, soweit ich weiß ist JAXB nur für XML?
Deinen Lösungsansatz verstehe ich so,dass ich mir die Jackson-Klassen nehme und eigene Klassen davon ableite und diese anpasse. So meinst du das,oder? 
Danke erstmal für diesen wertvollen Hinweis.


----------



## stg (1. Nov 2015)

distortion85 hat gesagt.:


> soweit ich weiß ist JAXB nur für XML?



_Eigentlich_ ja, aber ob man mit Hilfe der über die Annotationen gelieferten Metainformationen nun XML oder einen JSON-String generiert ist ja nahezu egal. Und daher wird auch genau das gerne gemacht. Siehe zum Beispiel hier:
http://www.adam-bien.com/roller/abien/entry/jaxb_json_pojo_serialization_example
http://blog.bdoughan.com/2013/03/moxys-xmlinversereference-is-now-truly.html



distortion85 hat gesagt.:


> Das ist interessant. Das Problem mit der Rekursion ist mir begegnet und ich hatte es mit den den Annotiationen *@JsonManagedReference* bzw *@JsonBackReference *unterbunden.


Das ist auch ein richtiger Ansatz von mehreren möglichen. Vielleicht fehlt dir einfach das letzte Stückchen. Speziell für bidirektionale Relationen mit Jackson kannst du auch mal hier weiterlesen:
http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion


----------



## distortion85 (1. Nov 2015)

Ich führe mir die Quellen erstmal zu Gemüte! Danke


----------



## distortion85 (4. Nov 2015)

Danke für die Quelle, nach einigem Studieren und Probieren habe ich gemerkt, dass es der falsche Weg ist, an der JSON-Ausgabe rumzutüfteln. Eine bessere Lösung wäre ja, schon in der Datenbankschicht die passenden Queries abzusetzen. Und nicht das JSON nachher als Rückgabe der REST-Schnittstelle nach den gewünschten Informationen zu parsen.
Die Beziehung Instrument<--->Musiker habe ich nun auf n<--->1 festgelegt.
Nun interessiert mich folgender Fall: Wie setze ich über die JPQL eine Query ab, die mir alle Instrumente zurückgibt, die vom Musiker X während der Veranstaltung Y gespielt werden?
Scheint ziemlich komplex über mehrere Tables, ich hatte so etwas versucht:


```
SELECT v, a, i from Veranstaltung v, Auftritt a, Instrument i WHERE i.Musiker.id=<Id_des_Musikers> AND v.id=<id_der_veranstaltung>
```

Funktioniert leider noch nicht so, wie ich das gerne hätte...


----------



## stg (10. Nov 2015)

distortion85 hat gesagt.:


> Funktioniert leider noch nicht so, wie ich das gerne hätte...



Da musst du schon konkreter werden, wenn du dir Hilfe erhoffst.


----------



## KSG9|sebastian (19. Nov 2015)

Du solltest dir mal die Grundlagen durchlesen. JPQL funktioniert mit den Attributnamen / Beziehungen aus deinem Datenmodell, z.B.

```
from Instrument i
inner join i.musiker m
inner join i.auftritt a
inner join a.veranstaltung v
where m=:musiker and v=:veranstaltung

query.setParameter("musiker", m);
query.setParameter("veranstaltung", v);
```


----------

