Dienstag, 13. März 2012

Behandlung von Value Types in JPA Hibernate

Wie wird mit dem Thema value types in JPA / Hibernate umgegangen?
Zunächst einmal die Definition von value types.
Value types sind keine echten Entitäten. Sie haben keinen Lebenszyklus, dass bedeutet sie werden nicht angelegt, editiert oder gelöscht. Sie gibt es seit Anbeginn des Systems.
Echte Entitäten, also mit @Entity gekennzeichnet, haben sehr wohl einen Lebenszyklus und haben eine entsprechende Repräsentation in der Datenbank.
Nun gibt es diverse Fälle wie man value types nutzen möchte:
  • als Konstanten, die bei dem entsprechenden Attribut der Entität in der Datenbank gespeichert wird
  • Werte, die lediglich als solche zu einer betreffenden Entität gespeichert werden sollen
Konstanten können schön mit Java Enums definiert werden:
public enum EnumXY{
   constantValue1, constantValue2, constantValue3;
}

Verwendet werden können die Konstanten in jeder Entität:
@Entity
public class MyEntity implements Serializable {
    ...
    @Enumerated
    private EnumXY kennzeichen;
    ...
}

In der Tabelle wird nun im Default die Position des Wertes(Ordinalzahl) der betreffenden Entität als Integer - Wert gespeichert. Würde also MyEntity das Kennzeichen constantValue3 zugewiesen bekommen, dann stünde der Wert 2 in der Tabelle von MyEntity. Dies kann über @Enumerated(EnumType.ORDINAL) (default) oder @Enumerated(EnumType.STRING) gesteuert werden. Beim letzteren wird der Name der Konstante in der betreffenden Spalte in der Datenbank gespeichert. Hier also constantValue3.

Was ist mit den Fällen, in denen man mehrere Werte eines value types zu einer Entität speichern möchte?
Auch dies ist nun mit JPA 2 möglich:
Mittels @ElementCollection wird deklarativ bestimmt, dass die Collection aus Werten eines value types besteht und sich nicht wie gewöhlich um eine Collection bestehend aus Entitäten handelt.
@ElementCollection
private List<String> basetypeValues = new ArrayList<String>();
Erst einmal CollectionsOfElements ist die Hibernate spezifische Annotation.
In JPA gibt es hierfür @ElementCollection.
Beispiel:
@Entity
public class X implements Serializable {
  @Id
  @Generated
  private Long id;
  @ElementCollection
   private List<String> remarks = new ArrayList<String>();
    ...
}

@Test
public void testElementCollection() {
  ...
  X x = new X();
  private List<String> remarks = new ArrayList<String>();
  remarks.add("remark1");
  remarks.add("remark2");
  remarks.add("remark3");
  x.setRemarks(remarks);
  em.persist(x);
  ...
}

Was passiert in der Datenbank?
Eine "ElementCollection" wird immer in einer separaten Tabelle gespeichert.
Diese kann man noch genauer über @CollectionTable definieren, dabei dient joinColum(s) zur Definition des foreignKey(s):
@CollectionTable(
   name = "nameOfCollectionTable",
   joinColumns = @JoinColum(name="fk")
)

Resultat:

Table X:
id column1 column2
3 .....         ....

Table Remarks:
id remarks 
3  remark1
3  remark2
3  remark3








Keine Kommentare:

Kommentar veröffentlichen