# Enums und passendes Mapping



## Naryxus (10. Nov 2016)

Hallo,

ich hätte da mal eine Frage zur best practice bezüglich "Enums" in der Datenbank und Enums in Java.

Bevor ich vor einigen Jahren angefangen habe, mich mit Java zu beschäftigen, habe ich mich einige Zeit mit Webprogrammierung beschäftigt.

Es kann natürlich sein, dass ich mit folgendem Beispiel schon falsch liege, aber ich möchte es trotzdem einmal formulieren:
Angenommen ich habe einen Benutzer, der verschiedene Rollen, wie zum Beispiel "Admin", "Moderator" oder lediglich "Benutzer" haben kann. Darüber hinaus sei angenommen, dass die Rollen später erweitert werden können, wie zum Beispiel mit "Verbannter".
Rein von dem Datenbankdesign her würde ich das lösen, indem ich eine Tabelle für die Rollen erstellen würde mit einer ID als Primärschlüssel und einem String als Namen der Rolle. Schließlich würde ich in der User-Table eine Spalte "Rolle" einführen, die den Fremdschlüssel auf die ID in der Rollentabelle enthält.

Wenn ich jetzt aber davon ausgehe, dass ich die Modellierung zunächst in Java vornehmen würde, würde ich für die Rollen ein Enum erstellen und dann in der User-Klasse ein Attribut dieses Enums einführen würde.
Angenommen, ich möchte aber dann die Persistenz der Objekte über die JPA API gewährleisten, dann könnte ich zwar mit der @Enumerated-Annotation das Enum speichern. Allerdings bietet mir die Annotation nur die Möglichkeit, die Rolle in der Datenbank entweder als String über den Namen zu speichern, was offensichtlich schlecht für spätere Änderungen in der Datenbank wäre, da stets alle Einträge mit dem entsprechenden Namen geändert werden müsste, wenn ich den Namen des Enums ändern würde.
Oder als Ordinalszahl, wobei sich mir hier die Frage stellt: Werden dabei trotzdem die Namen der Enums in einer Tabelle gespeichert, oder wird hier lediglich tatsächlich nur die Zahl gespeichert? Bei letzterem könnte ich die Datenbank ja nur bedingt exportieren, ohne die Java-Enum-Klasse mit zu exportieren, da mir ja sonst essentielle Informationen fehlen (Um später zum Beispiel zusätzlich mit einem PHP-Skript auf die Datenbank zuzugreifen).

Grüße


----------



## stg (10. Nov 2016)

Es liegt in der Natur von Enums, dass man diese eben (im Normalfall) nicht (nachträglich) ändert. Und wenn doch, dann sind das wenige Ausnahmefälle, in denen man ruhig mal alle Datensätze einer Tabelle anpacken kann. Das sollte man nur nicht andauern im Betrieb der Anwendung machen. 



Naryxus hat gesagt.:


> Werden dabei trotzdem die Namen der Enums in einer Tabelle gespeichert



Nein, werden sie nicht. Aber das hält dich ja nicht davon ab das trotzdem zusätzlich zu machen. Wie schon gesagt: Das sind ja statische Informationen, da ist das schon OK so..

Du kannst natürlich auch eine JPA Entity "UserRole" anlegen und den Feld mit dem Namen auf dein Enum mappen. Das ist dann nur ein bisschen "doppelt gemoppelt" und du brauchst einen zusätzlichen JOIN um die Rolle eines Users abzufragen. 

Du hast übrigens nicht nur die Möglichkeit toString() oder ordinal() zu mappen, sondern du kannst auch dein eigenes individuelles Mapping festlegen. Aber das löst dein Problem hier auch nicht.

Insgesamt: ordinal() zu mappen finde ich "gefährlich", das vermeide ich meistens. Es gibt Gründe, die dafür sprechen können, aber da sind wir meist im Bereich von Mikrooptimierungen, die meistens nicht interesant sind. Map einfach den Namen, das versteht jeder sofort, wenn er es liest. Und du musst die Rollen ohnehin an mehreren Stellen pflegen, wenn es da Änderungen gibt (in den Konfigurationen deines Anwendungsservers, im Code selbst usw...)


----------



## Naryxus (11. Nov 2016)

stg hat gesagt.:


> Es liegt in der Natur von Enums, dass man diese eben (im Normalfall) nicht (nachträglich) ändert.



Ach echt? Das wusste ich bisher nicht. Wie würdest du denn dann die Möglichkeit abbilden, neue Rollen zu erstellen, bzw den Namen zu ändern? Ich meine halt von der Funktion her sind die Rollen lediglich festgelegte Zeichenketten, auf die dann bei bestimmten Methoden geprüft wird, ob die Methode jeweils erlaubt ist. Ich finde halt in der Implementierung eigentlich eine extra Klasse dafür anzulegen, die als @Entity annotiert wird ein wenig übertrieben.


----------



## Joose (11. Nov 2016)

Naryxus hat gesagt.:


> Wie würdest du denn dann die Möglichkeit abbilden, neue Rollen zu erstellen, bzw den Namen zu ändern?


Als Enum gar nicht 
Berechtigungen und Rollen würde ich in diesem Fall in die Datenbank auslagern, da so jederzeit die Rollen und Berechtigungen angepasst werden können.
Nur in Ausnahmefällen würde ich hier auf Enum setzen (zb sehr selten verwendete Software, wo nicht viel mit Berechtigungen hantiert wird).

Ob du nun eine extra Klasse schreibst oder eine entsprechendes Enum ist ja egal ... bei beiden wird eine Datei erstellt. Klar bei dem einen musst du noch das laden/speichern aus/in die Datenbank realisieren, mittels ORM ist sowas aber rasch implementiert.


----------



## Naryxus (11. Nov 2016)

Joose hat gesagt.:


> Klar bei dem einen musst du noch das laden/speichern aus/in die Datenbank realisieren, mittels ORM ist sowas aber rasch implementiert.



Bei einer Klasse ist mir das bewusst. Da würde ich das dann als Entity deklarieren. Allerdings wäre ja genau das meine Frage gewesen, ob ich Enums dann auch mittels ORM speichern kann. Also im Prinzip eine Tabelle, die alle Enums enthält mit einer ID und eben dem Namen.


----------



## Joose (11. Nov 2016)

Du wirst die Enums vielleicht irgendwie in einer Tabelle speichern können.
Aber du kannst dann nicht die Tabelle ergänzen/anpassen und neue Werte ins Enum laden.


----------



## Naryxus (11. Nov 2016)

Joose hat gesagt.:


> Aber du kannst dann nicht die Tabelle ergänzen/anpassen und neue Werte ins Enum laden.


Okay. Dann werde ich doch wohl eher eine Klasse benutzen.


----------

