Announcement

Collapse
No announcement yet.

Vererbung mit Hibernate Annotations

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Vererbung mit Hibernate Annotations

    Hallo ihr Wissenden ;-),

    ich bin Student und befasse mich seit etwas mehr als einem Monat mit Java. Also ich bezeichne mich selber mal als Newbee, auch wenn ich schon Erfahrung mit C# und PHP habe.

    Nun wir müssen einen Online-Shop mit Hilfe von Java realisieren und sollen dafür den Anwendungskern entwickeln. Also GUIs sind nicht von Bedeutung. Damit der Kern frei von SQL-Statements ist, wird JPA mit EJB 3 eingesetzt.

    Sollten hier schon Fehler bei der Beschreibung sein, bin ich euch nicht böse, wenn ihr da vielleicht etwas zur Lückenschließung beitragen könntet. Ich bin ja lernfähig. :-)

    Nun aber zum Problem. Das Datenbankdesign ist entwickelt worden und steht. Die Verbindung zur Datenbank (PostgreSQL) ist im Eclipse konfiguriert und funktioniert auch. Auch sind schon Dummy-Daten in der DB eingepflegt.

    Nun müssen meine Objekte, die ich im Programm verwenden will mit der DB verknüpft werden und dabei komme ich nicht um eine Vererbung herum.

    Das sieht von der Objektseite so aus:
    Code:
    abstract class UnknownUser implements java.io.Serializable { .. }
    // von dieser Klasse sollen keine Objekte erstellt werden
    
    public class Gast extends UnknownUser implements Serializable { .. }
    // Objektklasse für Benutzer ohne Registrierung -> minimale Rechte
    
    abstract class Benutzer extends UnknownUser implements Serializable { .. }
    // von dieser Klasse sollen keine Objekte erstellt werden
    
    public class Kunde extends Benutzer implements Serializable { .. }
    public class Mitarbeiter extends Benutzer implements Serializable { .. }
    public class Lieferant extends Benutzer implements Serializable { .. }
    public class Admin extends Benutzer implements Serializable { .. }
    Ich habe also eine zweifache Vererbung aufgebaut. Diese funktioniert auch von der Objektseite aus. Also je tiefer die Vererbung reicht, desto mehr Attribute hat das Objekt.

    Jetzt wird es aber haarig. In der DB habe ich eine zentrale Tabelle "Benutzer" in der für alle Objekte die Basisdaten bereitgehalten werden. Einzig das Objekt Gast unterscheidet sich von den Attributen nicht von UnknownUser. Der Benutzer erweitert den UnknownUser um Attribute, die in der Tabelle Benutzer stehen, die aber von UnknownUser nicht zur Verfügung gestellt werden sollen, weil Gast diese nicht erben soll. Die von Benutzer abgeleiteten Klassen Lieferant und Mitarbeiter haben eigene zusätzliche Tabellen aus denen die Attribute ausgelesen werden. Ansonsten ist in der Tabelle Benutzer eine Spalte Rolle, durch die die Objekte klassifiziert werden.

    Die Klassifizierung kann mittels @Inheritance und @DiscriminatorValue erfolgen, aber funktioniert scheinbar nicht so ganz. So wie ich das sehe müsste ich bei meiner Vererbung 2 Inheritance-Typen benutzen, einmal SINGLE_TABLE und zum anderen JOINED verwenden, aber ich komme damit momentan einfach nicht klar. Kann mir vielleicht jemand einen Denkanstoss geben?

    Vielen, vielen Dank
    Stefan
    Attached Files

  • #2
    @Entity
    @Inheritance(strategy=InheritanceType.SINGLE_TABLE )
    @DiscriminatorColumn(name="subclass")

    sagt hibernate nur, wie eine Vererbung gemappt werden soll. Ob in einer Tabelle oder in mehreren. Native Datentypen werden dann auch -wie immer- gemappt. Unbekannte Entitys müssen weiterhin in der Klasse mit @onetomany o.a. gemappt werden.

    Also kannst du wenn du die Vererbung in einer Tabelle haben willst o.a. Codezeilen in UnknownUser einfügen.
    Und die unbekannten Entitys müssen eine Mappinganweisung erhalten.
    Christian

    Comment


    • #3
      Danke Christian, aber ich muss ehrlich zugeben, dass ich noch nicht ganz verstanden habe, was Du meinst. Vielleicht könntest Du mir ja noch einmal auf die Sprünge helfen. Danke schonmal für Deine Mühe.

      Also die Superclass UnknownUser referenziert die Tabelle Benutzer, allerdings nur wenige Spalten davon. Da die nächsten Erben Gast und Benutzer weitere Spalten aus der Tabelle Benutzer auslesen, muss doch der Inheritance-Type auf "Joined" sein, oder nicht?

      Im weiteren Vererbungsbaum des Objektes Benutzer muss dann teilweise zur Tabelle Benutzer eine weitere Tabelle mit spezifischen Objekt-Daten ausgelesen werden und hier bekomme ich dann Probleme, da "Joined" hier nicht mehr möglich ist und JPA anmerkt, dass keine zweite Annotation @Id (für die zusätzliche Tabelle) erlaubt sei.

      Ich bin weiterhin für Eure Hilfe sehr dankbar. Würde mich freuen, wenn mir jemand helfen könnte und ich daraus lernen kann.

      Comment


      • #4
        Bei Hibernate ist es besser nicht die Beziehung zu Tabellen und deren Spalten herzustellen. Vielmehr nur bei den Klassen bleiben. Was Hiberante dann daraus für Tabellen macht "ist seine Sache".

        Wenn UnknownUser die Klasse Benutzer referenziert ist zu prüfen, um was für eine Beziehung es sich handelt.

        Dann ist an der Liste oder dem einzelenen Objekt des Typs Benutzer in der Klasse UnknownUser diese Beziehung herzustellen (bsp. ManyToMany)

        Wenn eine weitere Klasse wie Gast ebenfalls die Klasse Benutzer referenziert, so ist wieder von neuem zu überlegen welche Beziehung besteht. Diese ist dann wieder an dem Objekt Benutzer in der Klasse Gast zu verankern

        Erbt allerdings die Klasse Gast den Benutzer von UnknownUser ist dort nix zu machen. Die Referenz wurde ja schon in der Superklasse angelegt.
        Christian

        Comment


        • #5
          Noch einmal ...

          Ich bins nochmal.

          Ich habe - möglicherweise - immernoch ein Problem mit meiner Vererbung. Wie folgt sieht die Objekt-Hierarchie aus:
          • UnknownUser
            • Gast
            • Benutzer
              • Kunde
              • Mitarbeiter
              • weitere (noch) nicht genutzte Objekte


          Das Objekt UnknownUser ist abstract. Nachdem ich feststellen musste, dass die Vererbungsstrategie Joined mit "erweiternden" Tabellen zu den Objekten nicht über Annotations lösbar ist - müsste via XML-Config gemacht werden - habe ich auf die Vererbungsstrategie "SINGLE_TABLE" gewechselt.

          Also allen Objekten der Hierarchie liegt eine Tabelle "Benutzer" zu Grunde, die alle gemeinsamen Daten speichert. Abhängig vom Objekt werden jedoch nicht alle Spalten ausgelesen.

          Das Objekt Mitarbeiter hat eine weitere Tabelle "Mitarbeiter", in der die Zuordnung zur Abteilung, in der der Mitarbeiter arbeitet aufgelöst wird. Diese Tabelle kann ich auch mit @SecondaryTable einbinden, im Hibernate SQL Preview wird der Join richtig aufgelöst.

          Jetzt gibt es aber Probleme mit der Abteilung.

          Die Tabelle Mitarbeiter hat folgende Spalten: benutzer_id (PFK), abt_id (FK)
          Die Tabelle Abteilung hat folgende Spalten: id (PK), abt_name, benutzer_id (FK)
          wobei die Spalte benutzer_id in der Tabelle Abteilung den Abteilungsleiter repräsentieren soll und derzeit noch nicht eingebunden ist.

          Wenn ich im HQL-Editor FROM Benutzer angebe, wird folgendes SQL-Query erzeugt:

          select
          benutzer0_.id as id39_,
          benutzer0_.benutzer_name as benutzer3_39_,
          benutzer0_.passwort as passwort39_,
          benutzer0_.email as email39_,
          benutzer0_.geburtsdatum as geburtsd6_39_,
          benutzer0_.mobil as mobil39_,
          benutzer0_.nachname as nachname39_,
          benutzer0_.telefax as telefax39_,
          benutzer0_.telefon as telefon39_,
          benutzer0_.vorname as vorname39_,
          benutzer0_2_.abteilung_id as abteilung4_47_,
          benutzer0_.rolle_id as rolle1_39_

          from
          swe_user.benutzer benutzer0_
          left outer join
          swe_user.mitarbeiter benutzer0_1_
          on benutzer0_.id=benutzer0_1_.benutzer_id
          left outer join
          swe_user.abteilung benutzer0_2_
          on benutzer0_.id=benutzer0_2_.abt_id
          where
          benutzer0_.rolle_id in (
          6, 2, 4
          )



          Der Fehler liegt offensichtlich in den größer geschriebenen Zeilen.
          Noch folgende Infos:
          Annotationen in der Mitarbeiter.java:

          ...snip...
          @SecondaryTable(name="mitarbeiter", pkJoinColumns=
          @PrimaryKeyJoinColumn(name="benutzer_id"))

          ...snip...
          @ManyToOne(optional=false)
          @JoinTable(name="abteilung", joinColumns=@JoinColumn(name="abt_id"))
          protected Abteilung abteilung = new Abteilung();



          Annotationen in der Abteilung.java:

          ...snip...
          @OneToMany(mappedBy="abteilung")
          private List<Mitarbeiter> mitarbeiter = new ArrayList<Mitarbeiter>(0);



          Ich habe alles probiert, aber nichts führt zur richtigen SQL-Query, also in den betreffenden Zeilen müsste


          benutzer0_2_.id as abteilung4_47_,

          bzw.

          on benutzer0_1_.abt_id=benutzer0_2_.id

          stehen.

          Vielleicht hat jemand einen Tipp, wie ich doch noch zum Ziel komme, ehe ich das ganze Wochenende an diesem Problem zubringe.


          Danke und viele Grüße
          Stefan
          Attached Files
          Zuletzt editiert von Stefan Iffland; 13.12.2008, 11:27. Reason: Anhang hochgeladen

          Comment


          • #6
            Ähnliche Probleme mit Hibernate hatte ich auch.

            Mir war die SQL-Anweisung, die Hibernate erzeugen sollte/musste, klar, aber ich hatte große Schwierigkeiten, Hibernate so zu konfigurieren damit auch wirklich der SQL-Befehl exakt, wie gewünscht, erzeugt wird.

            Dann habe ich mir mal iBATIS angeschaut und nutze seitdem kein Hibernate mehr. Die üblichen Operationen kann ich damit schneller umsetzen und ich bin mir der verwendeten SQL sicher, da ich sie selber geschrieben habe ;-)

            Comment

            Working...
            X