JPA : "generische" Collection persistieren

Cage Hunter

Aktives Mitglied
Hi Leute, lang ist's her, doch nun hab ich wieder ein schwer googlebares Problem entdeckt^^

Ich möchte ein modulares System bauen, in dem der Nutzer beliebige Komponenten "installieren" kann. Es werden auch künftig weitere installierbare hinzukommen, sonst würde ich die ganze Sache einfach statischer machen.

Der Code sieht in etwa so aus :

Java:
@Entity(name="AUser")
public class User implements Serializable
{
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @Column(nullable=true)
    private ArrayList<MyComponent> myComponents;
    ...
}
In "myComponents" sollen die Komponenten "installiert" werden.

Java:
@MappedSuperclass
public abstract class MyComponent implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    ...
}
So sieht eine Komponente aus, sie ist abstrakt weil sie nur zur Generalisierung dient und nicht viel kann^^

Java:
@Entity
public class AComponent extends MyComponent
{
   ...
}
DAS Ding ist mein eigentliches Ziel. Ich möchte "AComponent" in die ArrayListe vom User packen. Das ist ja Java-technisch kein Problem. Aber JPA findet schon den Versuch nicht sehr schön und meckert.
(Es würde auch meckern wenn ich "@MappedSuperclass" wegließe, weil er im Array natürlich MyComponents erwartet)

Also wie kann ich dieses Problem lösen? Geht das überhaupt, dass man eine generische Collection mit spezialisierten Objekten füllt???

Wie gesagt, anders wär's ja viel einfacher, aber würde ich jede neue Komponente als neues Member implementieren, würde die Tabelle von User ständig verändert und das ist echt schlecht im Fall, dass die Anwendung schon läuft und Leute registriert sind^^

Ich hoffe Ihr könnt mir helfen :(
 

Cage Hunter

Aktives Mitglied
Vielen Dank :)

Ich hab zwar etwas rumprobieren müssen (wär ja langweilig wenn mal was auf Anhieb funktionieren würde^^) aber nun läuft es wunderbar :)
Ich versteh zwar nicht ganz wieso JPA da Hilfe für braucht aber ok...

Ich hab die Superklasse nun folgendermaßen angepasst damit es läuft :

Java:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="COMPONENT_TYPE")
public abstract class MyComponent implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    ...
}

Zur Erklärung warum das jetzt so aussieht :
- Es muss @Entity sein, weil ich andernorts ja eine Array-Liste<MyComponent> persistieren will, auch wenn dort nie eine reine MyComponent drin landen wird
- Die Vererbungsstrategie "JOINED" ist notwendig damit JPA die Inhalte auftrennen/zusammenfügen kann. So landen die Gemeinsamkeiten aller von MyComponent geerbten Objekte in der "SuperTabelle" und alle unterschiede in ihren eigenen Tabellen
- Die DiscriminatorColumn muss gesetzt werden (er versucht es automatisch, nervt dann aber, dass diese gar nicht existiert^^) damit JPA von der SuperTabelle aus die erbende Tabelle findet, also einfach ein Typisierungsfeld als Tabellen-"zeiger"

[edit] Achja, ich hatte dieses Problem mit EclipseLink(JPA 2.0), habe aber gelesen, dass nicht alle Mapper unbedingt einen Discriminator benötigen, immerhin ein Feld, das man bei anderen Mappern evtl einsparen könnte :) [/edit]

Vielen Dank nochmal, endlich läuft der Mist :applaus:
 
Zuletzt bearbeitet:

Cage Hunter

Aktives Mitglied
Ja schon, aber JPA sollte schon damit zu recht kommen und evtl auch Zusammenhänge nachvollziehen *wunschdenk*
Wenn ich eine Collection für eine abstrakte Klasse anlege, dann könnte man daraus schliessen, dass dort definitiv keine abstrakten Objekte reinkommen werden^^
Hachja, hauptsache ich hab's verstanden und kann nun gut gelaunt weiter arbeiten :)
 

Ähnliche Java Themen


Oben