Es gibt 3 Arten von Beziehungen:
- 1:1
- 1:m
- n:m
Um Grails auf Herz und Nieren zu prüfen, werden in der Benutzerverwaltung für alle 3 Beziehungen Anwendungsfälle eingebaut. Um Problemen bei den Tabellennamen (z.B. bei Oracle) aus dem Weg zu gehen, ist es ratsam die Domain Klasse User in ManagedUser umzubenennen.
Davon ausgehend, dass unser Benutzer nur 1 Adresse hat, wird eine neue Domain Klasse für die Adressdaten angelegt. Den Einsatz von 1:1 Beziehungen sollte man sich reichlich überlegen, da sie nur zur logischen Trennung dienen, später aber zu Performance Problemen führen können.
grails create-domain-class
...
address
...
Die daraus generierte Datei Address.groovy
wird mit den Eigenschaften Ort, PLZ und Straße angepasst.
class Address {
Long id
Long version
String street
Long zipcode
String city
}
Eingebunden wird die Adresse beim Benutzer (ManagedUser.groovy
) wie folgt:
class ManagedUser {
...
Address address
}
Da wir zwar Benutzer haben, die an einem Ort wohnen, aber sehr kontaktfreudig sind, benötigen wir die Möglichkeit 1 oder mehrere Kontaktinformationen (Daten und Typ z.B. email oder phone) zu einem Benutzer abzuspeichen. Dafür ist eine neue Domain Klasse ContactData zu erstellen. Die 1:m Beziehung wird über die Eigenschaft belongsTo ausgedrückt. Ein Verweis auf den Benutzer erhält man über die Eigenschaft ManagedUser.
class ContactData {
Long id
Long version
String data
String type
ManagedUser mUser
static belongsTo = ManagedUser
}
Letzendlich fasst man Benutzer gern in Gruppen zusammen, um sie besser administrieren zu können. Da ein Benutzer zu ein oder mehreren Gruppen gehören kann und eine Gruppe ein oder mehrere Benutzer umfassen kann, haben wir hier eine typische Situation einer n:m Beziehung. Als erstes benötigt man für die Grupen eine eigene Domain Klasse. Bereits dort drückt man einen Teil der Beziehung über die Eigenschaft hasMany aus. Da die Gruppen den Benutzern zugeordnet werden sollen, ist zusätzlich die Eigenschaft belongsTo notwendig.
class ManagedGroup {
Long id
Long version
String name
static belongsTo = ManagedUser
static hasMany = [musers:ManagedUser]
}
Auch unsere Domain Klasse ManagedUser muss dafür noch angepasst werden. Vollständig sieht sie dann so aus:
class ManagedUser {
Long id
Long version
String firstname
String lastname
Date createdAt
Address address
static hasMany = [mgroups:ManagedGroup]
}
Die generierte Datenbankstruktur sieht danach so aus:
Der Ansatz, dass die Datenbank Struktur generiert wird, kann nur verwirklicht werden, wenn Projekte von Null anfangen. Oft setzen aber Produkte auf einem vorhandenen Backend auf. Spätestens dann muss man sich doch mit der Konfiguration von Hibernate auseinandersetzen, die in unserem Beispiel von Grails generiert wurde.
Das nächste Mal werde ich mich mit den Controllern befassen, die auf die Daten (Model) zugreifen, und sie an die View weiterreichen.
Zu dem Punkt:
Den Einsatz von 1:1 Beziehungen sollte man sich reichlich überlegen, da sie nur zur logischen Trennung dienen, später aber zu Performance Problemen führen können.
Mich würde der Grund dazu interessieren
Ich wollte in der Applikation alle Grails Beziehungen ausprobieren. In produktiven Anwendungen würde ich darauf verzichten, da im Hintergrund 2 Tabellen angelegt werden, die bei einer Abfrage im Hintergrund erst durch einen Join in der Abfrage miteinander verbunden werden müssen.
Beim Löschen eines Benutzers (auf Datenbankebene) muss man zusätzlich aufpassen, dass der Adressdatensatz auch gelöscht wird. Sonst gibt es Datenleichen.