Map mit enum keys

strgF

Mitglied
Hallo ich habe die folgende entity.
Java:
@Entity
@Table(name = "statusvalues")
public class StatusValuesEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private  Map<StatusTypes, Integer> values;
}
Bei den keys der Maps handelt es sich um enums.
Die enum Klasse StatusTypes sieht wie folgt aus

Code:
public enum StatusTypes {
    HP, ATK, SATK, DEF, SDEF, INIT;
}

Ich möchte jetzt, dass die Map values in die Tabelle statusvalues geschrieben wird. Dabei sollen in der Tabelle statusvalues neben der id die Spalten HP, ATK, SATK, DEF, SDEF und INIT angelegt werden. Gibt es dafür eine Annotation, die man values voranstellt oder wie könnte man das hinbekommen?
 

strgF

Mitglied
Letztlich soll initial sowas ausgeführt werden
SQL:
CREATE TABLE(
id integer(10) NOT NULL,
    hp varchar(3),
    atk varchar(3),
    ...
    PRIMARY KEY(id)
);

Dann sollen die Werte der Map den entsprechenden Spalten zugeordnet werden. Ich weiß halt nicht wie man das am besten mit jpa und hibernate machen könnte.
 

mihe7

Top Contributor
Dabei sollen in der Tabelle statusvalues neben der id die Spalten HP, ATK, SATK, DEF, SDEF und INIT angelegt werden. Gibt es dafür eine Annotation, die man values voranstellt oder wie könnte man das hinbekommen?
Nicht, dass ich wüsste und das wäre grundsätzlich auch keine gute Idee (bei einer Änderung des Enums müsste die Tabellendefinition geändert werden, Verletzung der 2. NF; mit entsprechender Begründung kann so etwas aber durchaus auch mal sinnvoll sein).

Abgesehen davon: Deiner Map nach zu urteilen, willst Du einen Statustypen auf einen Wert abbilden. Wie soll das funktionieren, wenn Du je Zeile mehrere Statustypen haben kannst?

Normalerweise willst Du eine ElementCollection verwenden, so dass die Werte in einer separaten Tabelle verwaltet werden.
 

strgF

Mitglied
Nicht, dass ich wüsste und das wäre grundsätzlich auch keine gute Idee (bei einer Änderung des Enums müsste die Tabellendefinition geändert werden, Verletzung der 2. NF; mit entsprechender Begründung kann so etwas aber durchaus auch mal sinnvoll sein).

Abgesehen davon: Deiner Map nach zu urteilen, willst Du einen Statustypen auf einen Wert abbilden. Wie soll das funktionieren, wenn Du je Zeile mehrere Statustypen haben kannst?

Normalerweise willst Du eine ElementCollection verwenden, so dass die Werte in einer separaten Tabelle verwaltet werden.
Danke für die Antwort

Wie würdest du es denn am besten machen?
Ich habe noch nicht soviel Erfahrungen mit Spring, JPA usw, weshalb ich nicht weiß was best practice ist.

Ich habe die Annotation @ElementCollection ausprobiert, aber dann kommt beim Starten der Anwendung table status_values_entity_values not found.

Ich habe noch eine weitere Frage. Wenn ich eine JPA entity habe und diese in einer Controller Methode,
die an einen request endpoint gemappt ist direkt übergebe, funktioniert das zwar, aber Sonar meckert
dann mit dieser Regel.
https://rules.sonarsource.com/java/tag/spring/RSPEC-4684

Was ist denn dann best practice? Sollte man von jeder Entity zwei Versionen haben. Einmal als JPA Entity und einmal ohne JPA?
oder ist es besser an die gemappte Methode eine Map zu übergeben und anhand dieser Map dann in der Methode die gewünschte JPA Entity, die dann auf der Datenbank gespeichert wird. Am Frontend verwende ich Thymeleaf, wobei die Attribute dann über input felder eines Formulars übergeben werden.

Was genau ist eigentlich der Unterschied zwischen DTO, DAO und POJO?
 

mihe7

Top Contributor
Wie würdest du es denn am besten machen?
Ich habe noch nicht soviel Erfahrungen mit Spring, JPA usw, weshalb ich nicht weiß was best practice ist.
Ich weiß nicht genau, was Du eigentlich vor hast und denke, dass Du die Entity vermutlich nicht brauchst bzw. nur hast, um etwas zu machen, was die ElementCollection liefert. Das, was ich oben geschrieben habe, hat erstmal nichts mit Best Practice von JPA zu tun.

Machen wir mal ein anderes Beispiel, dann kann man damit eher was anfangen. Nehmen wir mal an, Du möchtest zu einem Kontakt jeweils eine(!) Telefonnumer privat, Telefonnummer geschäftlich und Handynummer speichern. Im Programm hast Du eine Aufzählung (enum), die den Nummerntyp (PRIVATE, OFFICE, MOBILE) angibt und dem entsprechend in der Klasse Contact eine Map<PhoneType, String> phoneNumbers.

Jetzt könntest Du hergehen und die Tabelle so gestalten:
SQL:
CREATE TABLE contact (
    id integer(10) NOT NULL PRIMARY KEY,
    name varchar(50) NOT NULL,
    phone_private varchar(255),
    phone_office varchar(255),
    phone_mobile varchar(255)
);

So eine Tabelle kann die 1. NF verletzen, das ist ein Stück weit Ansichtssache, je nachdem wie konstant man den Aufzählungstyp sieht (ist der Wertebereich wirklich konstant oder kann er sich schon mal ändern). Verletzt sie die 1. NF nicht, dann wäre die Tabelle sogar in der 3. NF. Natürlich speichert man so aber auch ggf. viele Werte, die man nicht braucht. Gibt es z. B. in 95 % nur eine Telefonnummer speichert man in 95 % jeweils zwei Werte umsonst.

Das ließe sich einfach umsetzen, indem Du in der Entity entsprechende String-Spalten anlegst. Nach außen kann die Klasse mit der Aufzählung arbeiten.

Eine andere Möglichkeit ist es, eine ElementCollection zu verwenden:
Java:
@Entity
public class Contacts {
// ...
    @ElementCollection
    @MapKeyEnumerated(STRING)
    @CollectionTable(name="CONTACT_PHONES", joinColumns=@JoinColumn("CONTACT_ID"))
    @MapKeyColumn(name="PHONE_TYPE")
    @Column(name="PHONE_NUMBER", length=50, nullable=false)
    private Map<NumberType, String> phoneNumbers;
}

Dann wird eine zusätzliche Tabelle verwendet:
SQL:
CREATE TABLE CONTACT_PHONES (
    CONTACT_ID integer(10) NOT NULL,
    PHONE_TYPE varchar(7) NOT NULL,
    PHONE_NUMBER varchar(50) NOT NULL,
    FOREIGN KEY fk_cpc (CONTACT_ID) REFERENCES contacts(ID),
    PRIMARY KEY pk_cpc (CONTACT_ID, PHONE_TYPE)
);

Die Beispiele sind alle nur hier im Editor geschrieben, kann also sein, dass da Fehler enthalten sind.
 

mihe7

Top Contributor
Was ist denn dann best practice?
Spring: keine Ahnung.

Was genau ist eigentlich der Unterschied zwischen DTO, DAO und POJO?
Ein POJO ist einfach die Bezeichnung für Objekte, die Instanzen von Klassen sind, an die keine besonderen Anforderungen gestellt werden (plain old java object).

Ein DAO ist ein Data Access Object, also ein Objekt, das nicht nur die Daten sondern auch gleich die Zugriffslogik (wie z. B. load, save, find usw.) enthält.

Ein DTO ist ein Data Transfer Object - um Daten über die Leitung zu schicken, z. B. um feingranulare Zugriffe zu vermeiden.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Y @OneToMany Liste Probleme mit Identity Keys Data Tier 2

Ähnliche Java Themen

Neue Themen


Oben