[NEWSboard IBMi Forum]
  1. #1
    Registriert seit
    Mar 2005
    Beiträge
    74

    Hibernate-Entity mit Verweisen aus mehreren zusammengesetzten Schlüssel

    Hallo,

    ich versuche micht derzeit an Hibernate und möchte gerne unsere Datenbank mit Hibernate mappen.

    Dabei stosse ich auf das Problem, das wir verweise auf andere Entitäten haben (@ManyToOne), die aus mehreren zusammengesetzten Schlüsselfelder bestehen. Dabei teilen sich die Verweise einzelnen Spalten aus der Tabelle. Als Beispiel Kunde-Id und Versandadresse-Id auf Versandadresse und Kunde-Id und Ansprechpartern-Id auf Ansprechpartern wobei sich beide Relationen die Kunden-Id teilen sowie Kunden-Id noch selber für die Kunden-Entität.

    Bei Hibernate habe ich nun das Problem, das ich Abbrüche bekomme:
    "Repeated column in mapping for entity: ft.Kommission column: aekdn (should be mapped with insert="false" update="false")"

    Wenn ich das @JoinColumn auf insertable=false und updateable=false setze, funktioniert zwar der Abruf aber ich kann z.B. den Ansprechpartner nicht mehr update bzw. schreiben.

    Kennt jemand das Problem, gibt es ein Möglichkeit das richtig umzusetzen?

    Gruß
    Martin

  2. #2
    Registriert seit
    Oct 2004
    Beiträge
    240
    Kennt jemand das Problem...
    Ja, ein typisches Problem mit Legacydateien. Wobei die meisten Verknüpfungen im Normalfall die verknüpfte Datei ja nicht mitändern sollen. Also z.B. wenn zu den Aufträgen die Kunden verknüpft sind, ist die "Read only" Verknüpfung kein Problem.

    Um das noch einmal zu verdeutlichen, die nachfolgenden Erweiterungen brauchst du nur, wenn du auch den Inhalt der verknüpften Daten ändern willst. Die Schlüsselfelder werden auch bei insert/update=false mitgespeichert.

    Beispiel: Aus einer Listbox wird eine der möglichen Versandadressen ausgewählt und zugewiesen. Damit werden die Id's beschickt und diese werden auch gespeichert.


    ..gibt es ein Möglichkeit das richtig umzusetzen?
    Am schönsten sind neue Dateien mit Id's als Schlüssel bzw. Fremdschlüssel.

    Eine weitere Möglichkeit sind Surrogate Keys, also zusätzliche Id's für den "Dualbetrieb" (alte und neue Programme). Hier der entsprechende Wiki Eintrag.

    Wenn man die Dateien nicht erweitern bzw. ändern darf/kann, bietet es sich diese fixen Verknüpfungen in der Service/DAO-Schicht zu implementieren.
    Also z.B. im AuftragService, Methode
    persistAuftrag(Auftrag auftrag)
    wird auch die abweichende Adresse gespeichert.

  3. #3
    Registriert seit
    Mar 2005
    Beiträge
    74
    Zitat Zitat von RobertPic Beitrag anzeigen
    Ja, ein typisches Problem mit Legacydateien. Wobei die meisten Verknüpfungen im Normalfall die verknüpfte Datei ja nicht mitändern sollen. Also z.B. wenn zu den Aufträgen die Kunden verknüpft sind, ist die "Read only" Verknüpfung kein Problem.

    Um das noch einmal zu verdeutlichen, die nachfolgenden Erweiterungen brauchst du nur, wenn du auch den Inhalt der verknüpften Daten ändern willst. Die Schlüsselfelder werden auch bei insert/update=false mitgespeichert.

    Beispiel: Aus einer Listbox wird eine der möglichen Versandadressen ausgewählt und zugewiesen. Damit werden die Id's beschickt und diese werden auch gespeichert.



    Am schönsten sind neue Dateien mit Id's als Schlüssel bzw. Fremdschlüssel.

    Eine weitere Möglichkeit sind Surrogate Keys, also zusätzliche Id's für den "Dualbetrieb" (alte und neue Programme). Hier der entsprechende Wiki Eintrag.

    Wenn man die Dateien nicht erweitern bzw. ändern darf/kann, bietet es sich diese fixen Verknüpfungen in der Service/DAO-Schicht zu implementieren.
    Also z.B. im AuftragService, Methode
    persistAuftrag(Auftrag auftrag)
    wird auch die abweichende Adresse gespeichert.

    Bist Du sicher das die Schlüsselfelder auch bei insert/update=false mitgespeichert werden? Nur die Schlüsselfelder zu speichern ist genau das, was ich möchte. Ich habe das ausprobiert und es ist leider nicht so. Oder mache ich etwas falsch. Hier mal die Source:

    Code:
    package ft;
    import java.io.Serializable;
    import javax.persistence.Column;
    import javax.persistence.Embeddable;
    import javax.persistence.EmbeddedId;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinColumns;
    import javax.persistence.ManyToOne;
    import javax.persistence.MapsId;
    import javax.persistence.Table;
    import javax.persistence.Transient;
    import buchhaltung._incubator.Kostenstelle;
    import core.Firma;
    @Entity
    @Table(name="aekomp")
    public class Kommission implements Serializable{
     
     @EmbeddedId
     private DatabaseId id;
     
     @MapsId("firma_id")
     @JoinColumn(name="aefa")
     @ManyToOne(fetch=FetchType.LAZY)
     private Firma firma;
     
     @Column(name="aelus")
     private String bezeichnung;
     @ManyToOne(fetch=FetchType.LAZY)
     @JoinColumns({@JoinColumn(name="aefa", referencedColumnName="kofa", updatable=false, insertable=false), 
       @JoinColumn(name="aekst", referencedColumnName="kost", updatable=false, insertable=false)})
     private Kostenstelle kostenstelle;
     
     
     @Embeddable
     public static class DatabaseId implements Serializable{
     
      @Column(name="aefa")
      int firma_id;
      @Column(name="aekom")
      int kommissions_id;
     
      public DatabaseId() {
      }
     
      public DatabaseId(int firmaId, int kommissionsId) {
       super();
       firma_id = firmaId;
       kommissions_id = kommissionsId;
      }
      @Override
      public int hashCode() {
       final int prime = 31;
       int result = 1;
       result = prime * result + firma_id;
       result = prime * result + kommissions_id;
       return result;
      }
     
      @Override
      public boolean equals(Object obj) {
       if (this == obj)
        return true;
       if (obj == null)
        return false;
       if (getClass() != obj.getClass())
        return false;
       DatabaseId other = (DatabaseId) obj;
       if (firma_id != other.firma_id)
        return false;
       if (kommissions_id != other.kommissions_id)
        return false;
       return true;
      }
     
     
     }
     public Firma getFirma() {
      return firma;
     }
     public void setFirma(Firma firma) {
      this.firma = firma;
     }
     public Kostenstelle getKostenstelle() {
      return kostenstelle;
     }
     public void setKostenstelle(Kostenstelle kostenstelle) {
      this.kostenstelle = kostenstelle;
     }
     
     
     public String getBezeichnung() {
      return bezeichnung;
     }
     public void setBezeichnung(String bezeichnung) {
      this.bezeichnung = bezeichnung;
     }
     @Override
     public String toString() {
      return id.kommissions_id+" "+getBezeichnung();
     }
    }
    Wenn ich das folgendes ausführe:
    Code:
    kommission.setKostenstelle(kostenstelle); kommission.setBezeichnung("TEST");
    session.update(kommission);
    session.flush();
    Erstellt Hibernate folgende Anweisung:
    Code:
    Hibernate: update aekomp set aelus=? where aefa=? and aekom=?
    Wobei die Kostenstelle (aekst) nicht aktualisiert wird

  4. #4
    Registriert seit
    Oct 2004
    Beiträge
    240
    Bist Du sicher das die Schlüsselfelder auch bei insert/update=false mitgespeichert werden?
    Nein, da habe etwas zu schnell drübergeschaut. Ich habe meine Beans etwas "schlauer" gemacht. Wenn ein Objekt mit update/insert=false zugewiesen wird, erfolgt das zuweisen der Einzelwerte manuell.

    Also bei z.B.

    Code:
    public void setKostenstelle(Kostenstelle kostenstelle) {
    
        this.kostenstelle = kostenstelle;
         this.id.firma_id = kostenstell.getFirma_id();
    ... 
    }
    Damit brauchen sich die weiteren Programme nicht mehr um diesen Umstand kümmern und diverse GUI-Builder funktionieren damit dann auch.

Similar Threads

  1. iSeries mit mehreren virtuellen Instanzen
    By Christian.Hesse in forum IBM i Hauptforum
    Antworten: 2
    Letzter Beitrag: 25-11-06, 05:57
  2. SQL: Aus mehreren Feldern ein Datum erkennen
    By I0N in forum NEWSboard Programmierung
    Antworten: 2
    Letzter Beitrag: 21-11-06, 12:44
  3. SQL Case von mehreren Dateien
    By steven_r in forum NEWSboard Programmierung
    Antworten: 4
    Letzter Beitrag: 08-08-06, 09:34
  4. Einen Datensatz mit mehreren Sessions benutzen
    By JonnyRico in forum NEWSboard Programmierung
    Antworten: 6
    Letzter Beitrag: 12-05-05, 15:46
  5. SQL Update Problem mit mehreren Tabellen
    By neuling_ in forum IBM i Hauptforum
    Antworten: 2
    Letzter Beitrag: 18-05-04, 09:35

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • You may not post attachments
  • You may not edit your posts
  •