Referenz zwischen 2 Serialisierten Objekten

Bobblz

Mitglied
Hallo zusammen,

ich habe ein Prolem.

Und zwar habe ich 2 Klassen, User und Abteilung.
Ein User bekommt eine Instanz von Abteilung zugeordnet.
Beide Objekte werden getrennt von einander serialisiert. (ObjectOutputStream)

Wenn ich die Objekte wieder deserialisiere, dann passt die Referenz von der im User hinterlegten Abteilung zum eigentlichen Abteilung-Objekt nicht mehr.
Ich möchte die Abteilung, die an mehreren Usern hinterlegt wird, aber zentral pflegen und nicht jeden user abklappern und die Abteilung extra anpassen.

Was mache ich verkehrt, bzw. wie mache ich es richtig?

Grüße
 
Moin,

Wie wäre es mit einem ChangeListener den du jedem User mitgibst. Wenn sich etwas an der Abteilung änderst kommt ein event und du könntest in der Aktion die Abteilung dann aktualisieren.


Gruß, Orb.
 
Danke, aber das trifft es nicht.

User beinhaltet eine Abteilung. Wenn ich dann alle User und Abteilungen in einzelne Files serialisiere und sie nach dem Neustart wieder deserialisiere, dann habe ich "irgendein" Abteilungs-Objekt in meinem User, aber nicht genau das, das ich ebenfalls serialisiert habe.

Java:
public class User implements Serializable {
   
	private static final long serialVersionUID = -185634638412422231L;
	private String loginName;
	private java.lang.String usrName;
	private java.lang.String usrVorname;
	private java.lang.String usrMail;

	private Abteilung usrAbt;

}
Java:
public class Abteilung implements Serializable {
	
	private static final long serialVersionUID = 1225118650026505862L;
   	private java.lang.String abtBezeichnung;
   	private java.lang.String abtStandort;
   	private java.lang.String abtTel;
   	private java.lang.String abtFax;
   	private boolean abtSupport;
   	private boolean abtService;

}

Grüße
 
Kannst du vielleicht die Stelle posten an dem die Objekte aufeinander Treffen vor dem Beenden und den Abruf nach dem Neustart.
Weil wenn du nur ein Abteilungsorbjekt and die User übergibst müsste es eig. so sein, dass wenn du das Objekt veränderst es auf alle entsprechend überträgt. Wobei auch sein kann das ich gerade einen Denkfehler hab.^^
( Programmiere auch noch nicht sooo lange )
 
Hallo Bobblz,

Auf den ersten Blick würde ich sagen, du serialisierst alle Objekte beider Klassen, du solltest aber nur die User serialisieren, sie haben schließlich Referenzen auf die Abteilungs-Objekte und diese werden (sofern du Variable vom typ Abteilung in User nicht explizit als transient gekennzeichnet hast) sowieso mit serialisiert.

Zum besseren Verständnis poste ich dir noch einen Beispielcode aus dem Handbuch der Java Programmierung:
Dabei geht es um eine art Stammbaum.

Code:
import java.io.*;

public class Person
implements Serializable
{
  public String name;
  public Person mother;
  public Person father;

  public Person(String name)
  {
    this.name = name;
  }
}

Code:
import java.io.*;
import java.util.*;

public class Listing4108
{
  public static void main(String[] args)
  {
    //Erzeugen der Familie
    Person opa = new Person("Eugen"); 
    Person oma = new Person("Therese");
    Person vater = new Person("Barny");
    Person mutter = new Person("Wilma");
    Person kind1 = new Person("Fritzchen");
    Person kind2 = new Person("Kalli");
    vater.father = opa;
    vater.mother = oma;
    kind1.father = kind2.father = vater;
    kind1.mother = kind2.mother = mutter; 

    //Serialisieren der Familie
    try {
      FileOutputStream fs = new FileOutputStream("test3.ser");
      ObjectOutputStream os = new ObjectOutputStream(fs);
      os.writeObject(kind1);
      os.writeObject(kind2);
      os.close();
    } catch (IOException e) {
      System.err.println(e.toString());
    }

    //Rekonstruieren der Familie
    kind1 = kind2 = null; 
    try {
      FileInputStream fs = new FileInputStream("test3.ser");
      ObjectInputStream is = new ObjectInputStream(fs);
      kind1 = (Person)is.readObject();
      kind2 = (Person)is.readObject();
      //Überprüfen der Objekte
      System.out.println(kind1.name); 
      System.out.println(kind2.name);
      System.out.println(kind1.father.name);
      System.out.println(kind1.mother.name);
      System.out.println(kind2.father.name);
      System.out.println(kind2.mother.name);
      System.out.println(kind1.father.father.name);
      System.out.println(kind1.father.mother.name); 
      //Name des Vaters ändern
      kind1.father.name = "Fred"; 
      //Erneutes Überprüfen der Objekte
      System.out.println("---"); 
      System.out.println(kind1.name);
      System.out.println(kind2.name);
      System.out.println(kind1.father.name);
      System.out.println(kind1.mother.name);
      System.out.println(kind2.father.name);
      System.out.println(kind2.mother.name);
      System.out.println(kind1.father.father.name);
      System.out.println(kind1.father.mother.name); 
      is.close();
    } catch (ClassNotFoundException e) {
      System.err.println(e.toString());
    } catch (IOException e) {
      System.err.println(e.toString());
    }
  }
}

javaDeveloper2011
 
Hallo javaDeveloper2011,

das geht schon in die richtige Richtung.

Dass die Abteilung mit dem User serialisiert wird habe ich auch eben so gefunden.
Das möchste ich aber nicht.

Es soll auch Abteilungen geben, die aktuell keine User haben. Wie werden diese denn serialisiert?

Ich möchte, das jeder User eine REFERENZ auf die Abteilung bekommt. Diese Referenz soll erhalten bleiben. Wenn ich dann das Programm neu starte soll das richtige serialisierte Objekt anhand der Referenz gefunden werde. Wenn sich z.b. der Name der Abteilung ändert, soll sich das gleich auf alle Abteilungen beziehen, die bei den User-Objekten hinterlegt sind. Genau das funktioniert nicht.
Ich hinterlege bei User A die Abteilung B. Benenne Abteilung B in Abteilung C um. User A hat trotzdem noch Abteilung A, sollte aber Abteilung B anzeigen.

Grüße
 
Wenn sich z.b. der Name der Abteilung ändert, soll sich das gleich auf alle Abteilungen beziehen, die bei den User-Objekten hinterlegt sind
Das check ich nich o_O

Normalerweise kann ein User nur in einer Abteilung sein, dann wäre es doch eigentlich sinnvoller, wenn du in der Abteilung eine Liste einfügst und diese die User beinhaltet. Von mir aus können die User auch noch eine Referenz von der Abteilung haben (damit man in beiden Richtungen arbeiten kann), aber dann bräuchtest du nur noch die Abteilungen zu serialisieren. Die User würden dann zwangsweise durch den Aufenthalt in der Liste mitserialisiert werden. Wenn das allerdings mehr eine Art Datenbank-Tabellen-Geschichte werden soll, dann solltest du das nicht mit Referenzen machen. Die kannste zwar mit drin behalten, sollten dann aber als transient deklariert sein, damit se nicht mitserialisiert werden. Stattdessen vergibste deinen Abteilungen eine Art ID (könnte z.B. der Hash-Wert sein) und weist diese den Usern zu. Wenn du dann den ganzen Kram wieder deserialisierst, dann musst du halt prüfen welcher User welche ID gespeichert hat und zu welcher Abteilung diese gehört und schon kannst du die Referenzen wieder richtig zuweisen.

EDIT:
Mag sich vielleicht nach Mumpitz anhören, funktioniert aber und der Vorteil bei der ID-Variante ist, dass man alle Objekte in separate Dateien serialisieren kann. Wie gesagt, beim Deserialisieren muss man zwar dann auch ein wenig Prüfarbeit verichten, dafür läufts aber.

EDIT2:
Ok, das mit dem Hash-Wert ganz schnell vergessen, weil sobald sich was in der Abteilung ändert (z.B. der Name), ändert sich auch der Hash. Dann halt ganz simpel, wie auch in Datenbanken üblich, eine fortlaufende Nummer als ID nehmen und schon hat man auch das Problem gelöst.
 
Zuletzt bearbeitet:
Danke Akeshihiro,

du triffst die Sache!

Mit der ID-Geschichte habe ich es bisher auch gemacht. Lief super.
Es handelt sich hier um ein Schulprojekt, bei einer Zwischenabnahme hieß es aber vom Dozent, das sei schlecht so, ich solle mit Objektreferenzen arbeiten. Daraufhin habe ich es so umgebaut und bis auf Mehraufwand und Problemen habe ich nix feststellen können was besser sein soll.

Jetzt sitz ich seit heute Früh und versuch das zu lösen. Ich könnte die Objekte comparable implementieren lassen, aber um sicher vergleichen zu können bräuchte ich wieder eine ID, da sich alle andere Daten wie Abteilungsname,Ort,Tel,.. ändern können. Da wäre ich praktisch wieder am gleichen Punkt nur mit deutlichen Mehraufwand.

Grüße
Bobblz
 
Oder du erweiterst die Abteilungen eben um die eine Liste und packst da die User rein, dann kannst du eigentlich auch mit Referenzen arbeiten (habs noch nicht getestet). Dann brauchst du auch nur noch die Abteilungen zu serialisieren, da die User gleich mitserialisiert werden. Kann man gut finden, kann man schlecht finden, da hat jeder seine eigene Vorstellung.

Und das mit den IDs ist vielleicht nicht die schönste Art, aber wenns mit den Referenzen nicht klappt, dann bleibt einem ja kaum was anderes übrig.

EDIT:
Ich habs mal eben grad ausprobiert und das mit den Referenzen klappt, wenn man alles in eine einzige Datei schreibt (javaDeveloper hats ja schon vorgemacht). Wie das mit verschiedenen Dateien läuft probier ich gleich mal aus.

EDIT2:
Mit verschiedenen Dateien (für jedes Objekt eine eigene Datei) funktioniert das nicht, is wahrscheinlich genau das, was bei dir da die ganze Zeit über schief geht. Ich habe mir auch mal die Abteilungen ausgeben lassen und zwar die eingelesenen Abteilungen und auch die Abteilungen aus den Usern und diese weisen völlig verschiedene Referenzen auf. Bei der Variante mit alles in eine Datei zu schreiben sind die Referenzen alle wie sie sein sollen. Ich denke mal, dass beim Serialisieren alles richtig läuft, aber beim Deserialisieren aus mehreren Dateien werden vermutlich alle Objekte aus einer Datei jeweils dateienweise separat instanziert, was die unterschiedlichen Referenzen erklären würde.

Also entweder alles in eine Datei schreiben (dann aber auch auf die Reihenfolge achten, weil die gleiche Reihenfolge muss auch beim Einlesen eingehalten werden) oder wenn es verschiedene Dateien sein sollen, dann halt über eine Art ID die Sachen koppeln, anders gehts dann halt nicht.
 
Zuletzt bearbeitet:
Danke dir,

EDIT2 betrifft genau mein Problem! :)
Gut, dann werde ich um eine ID Kopplung nicht herumkommen.

Vielen Danke an alle Beteiligten!
 
Zurück