|
|
Anfängerfrage - Vorgehensfrage
-
07-31-2008, 06:25 AM |
-
fats
-
-
-
-
Joined on 07-28-2008
-
-
Posts 7
-
-
-
|
Anfängerfrage - Vorgehensfrage
Moin Allerseits! Ich hab mal die ersten eigenen Schritte mit db4o unternommen und hätte mal eine Frage zum Allgemeinen Vorgehen.
Mal ein paar Codeauszüge. Testszenario ist eine Userverwaltung. Ich habe zum einen eine schlichte Klasse Account : public class Account { private String username; private String password; public String getUsername() { return username; }
.... plus all die Getter/Setter ....
} und dazu einen Manager, der das Speichern und etwas Logik übernimmt: public class DbManager { private HashMap <String,String> accounts = new HashMap <String, Account>(); private String dbfile="E:/temp/userdb.yap"; .... }
Anmerkung: In der HashMap accounts halte ich alle einzelnen Accounts vor, die dem System bekannt sein müssen. Ziel ist es, nicht wegen jeder Anfrage gleich die DB kontaktieren zu müssen, denn DB Verbindungen aufbauen kostet Zeit, habe ich mal irgendwo gelernt ;) Ist das noch aktuell und auch bei db4o zubeachten?
In der Klasse DbManager hab ich Methoden zum Speichern und Laden von Accounts. public void save(Account a){ Configuration config = Db4o.newConfiguration(); config.objectClass(Account.class).cascadeOnUpdate(true); ObjectContainer db = Db4o.openFile(config,dbfile); try { //Lade Liste der Accounts, sonst haben die Änderungen beim Speichern keinen Erfolg ObjectSet <HashMap> result = db.queryByExample(accounts); //Wenn es die Liste gibt, dann weise sie der private HashMap accounts zu if (result.hasNext()){ accounts = result.next(); } // füge der HashMap den neuen Account a zu // Hier jetzt vereinfacht dargestellt. Es gibt hier keine Überprüfung, ob einen User schon existiert, // und er "nur" geupdated werden muß. (Vermutl. Kernproblem!) accounts.put(a.getUsername(), a); //Speichere die HashMap db.store(accounts);
} catch (DatabaseFileLockedException e) { e.printStackTrace(); } finally{ db.close(); } } public Account load(String username){ ... } Problematik: wenn ich einen User updaten möchte, dann kann ich ihn mir zwar mit Account a= load("Karl") raussuchen, das reine Objekt updaten mit a.setPassword("1234") und dann mittels save(a) speichern - eigentlich updaten in der DB! - aber das klappt so nicht! Ich vermute, es liegt daran, daß ich den Account außerhalb des db = Db4o.openFile ... db.close() "Blocks" verändere. Da reicht das speichern/updaten der HashMap wohl nicht aus - trotz cascadeOnUpdate. Richtig? Muß ich mir jetzt per db.queryByExample den Account aus der DB ziehen und die einzelnen neuen Werte des übergebenen Accounts a einzeln setzen? Das wäre aufwendig und für meinen ersten Eindruck unschön. Die große Frage: Wo wird die Speicherlogik implementiert? Baue ich einen Manager, der das für mich macht? Und wenn ja, baue ich einen zentralen für alle beteiligten Klassen, für jede Klasse ihren eigenen Manager oder kommt die Speicher- und Lade-Logik in die jeweilige Klasse (z.B. Account) selbst rein?? Dann wäre jede Klasse für sich für das Speichern und Laden verantwortlich.
Was sind eure Erfahrungen? Welches ist der sinnvollste Weg? Viele Grüße Fats
|
|
-
07-31-2008, 11:22 AM |
-
Origon45
-
-
-
-
Joined on 02-13-2008
-
Germany
-
Posts 97
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
Hi, ich versuche mal ein paar Antworten zu geben. fats: Anmerkung: In der HashMap accounts halte ich alle einzelnen
Accounts vor, die dem System bekannt sein müssen. Ziel ist es, nicht
wegen jeder Anfrage gleich die DB kontaktieren zu müssen, denn DB
Verbindungen aufbauen kostet Zeit, habe ich mal irgendwo gelernt ;) Ist
das noch aktuell und auch bei db4o zubeachten? Also das kommt drauf an, wie umfangreich und komplex deine Applikation wird und wie du sie aufbaust. Normal öffnet man ja die DB und lässt sie offen, so entfällt das aufwändige Öffnen der DB. Die Anfragen kosten natürlich auch Zeit, aber wenn es keine riesigen komplexen Abfragen sind, geht die Abfragen fix. Die Geschwindigkeit der Abfragen liegt dann an deinen Konfigurationen und anderen Einstellungen.
fats:public void save(Account a){ Configuration config = Db4o.newConfiguration(); config.objectClass(Account.class).cascadeOnUpdate(true); ObjectContainer db = Db4o.openFile(config,dbfile); try { //Lade Liste der Accounts, sonst haben die Änderungen beim Speichern keinen Erfolg ObjectSet <HashMap> result = db.queryByExample(accounts); //Wenn es die Liste gibt, dann weise sie der private HashMap accounts zu if (result.hasNext()){ accounts = result.next(); } // füge der HashMap den neuen Account a zu // Hier jetzt vereinfacht dargestellt. Es gibt hier keine Überprüfung, ob einen User schon existiert, // und er "nur" geupdated werden muß. (Vermutl. Kernproblem!) accounts.put(a.getUsername(), a); //Speichere die HashMap db.store(accounts);
} catch (DatabaseFileLockedException e) { e.printStackTrace(); } finally{ db.close(); } } public Account load(String username){ ... } Problematik:
wenn ich einen User updaten möchte, dann kann ich ihn mir zwar mit
Account a= load("Karl") raussuchen, das reine Objekt updaten mit
a.setPassword("1234") und dann mittels save(a) speichern - eigentlich
updaten in der DB! - aber das klappt so nicht! Ich vermute, es liegt
daran, daß ich den Account außerhalb des db = Db4o.openFile ...
db.close() "Blocks" verändere. Da reicht das speichern/updaten der
HashMap wohl nicht aus - trotz cascadeOnUpdate. Richtig? Muß
ich mir jetzt per db.queryByExample den Account aus der DB ziehen und
die einzelnen neuen Werte des übergebenen Accounts a einzeln setzen?
Das wäre aufwendig und für meinen ersten Eindruck unschön. 1. Du kannst deine Accountobjekte beliebig außerhalb der DB verändern, musst sie dann natürlich richtig updaten. 2. Das cascadeOnUpdate(true) ist auf die Klasse Account gelegt, anstatt auf die Hashmap-Klasse. 3. Wenn du einen user verändern willst, musst du erst die Hashmap laden, dann den User aus der Hashmap und den dann erst User updaten, speichern und dann auch die Hashmap wieder speichern.
Kannst du bitte mal die load procedure genauer zeigen? Wie sieht dein Klassensturktur grob aus, ich bin immernoch verwirrt. So wie ich das verstanden habe, hast du eine Klasse Account und eine andere Klasse die die Hashmap mit den Accounts enthält. Richtig? fats:
Die große Frage: Wo wird die
Speicherlogik implementiert? Baue ich einen Manager, der das für mich
macht? Und wenn ja, baue ich einen zentralen für alle beteiligten
Klassen, für jede Klasse ihren eigenen Manager oder kommt die Speicher-
und Lade-Logik in die jeweilige Klasse (z.B. Account) selbst rein??
Dann wäre jede Klasse für sich für das Speichern und Laden
verantwortlich.
Was sind eure Erfahrungen? Welches ist der sinnvollste Weg?
Das ist echt von deinen Anforderungen abhängig, natürlich ist es sinnvoll einen Manager zu bauen, meist einen zentralen. Die Logik zum Speichern würde ich nicht in die Klassen mit aufnehmen, ist nur unnötiger Ballast. Ich habe bis jetzt oft kleinere Anwendung geschieben, wo ich nicht unbedingt einen Manager gebraucht habe. In einem anderen Projekt habe ich einen zentralen Manager für die Speicherung verwendet und bin damit gut gefahren. Mfg Origon
Germany
|
|
-
08-01-2008, 09:37 AM |
-
fats
-
-
-
-
Joined on 07-28-2008
-
-
Posts 7
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
Moin! Origon45:Hi, ich versuche mal ein paar Antworten zu geben. [...] Kannst du bitte mal die load procedure genauer zeigen? Wie sieht dein Klassensturktur grob aus, ich bin immernoch verwirrt. So wie ich das verstanden habe, hast du eine Klasse Account und eine andere Klasse die die Hashmap mit den Accounts enthält. Richtig? [...]
Ok, ich poste mal den Code. Hab ihn auch schon etwas erweitert, aber bin noch nicht so ganz glücklich. --------------------------------------------------------------------------------------------------------------- public class Account { private String username; private String password; //Ob das Objekt bereits in der DB gesoeichert wurde private boolean saved=false; //Einfach nur eine Liste zum Ausprobieren. private ArrayList <String> history = new ArrayList<String>(); public Account(String username, String password){ this.username = username; this.password = password; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public boolean isSaved() { return saved; }
public void setSaved() { this.saved = true; } public void addHistory(String h) { history.add(h); } public ArrayList <String> getHistory(){ return history; } public void setHistory (ArrayList<String> h){ this.history = h; } // Kopiert die Werte von dem übergebenen Account-Objekt public void copyValuesFrom(Account a) { this.username = a.getUsername(); this.password = a.getPassword(); this.saved = a.isSaved(); this.history = a.getHistory(); } }
--------------------------------------------------------------------------------------------------------------- public class DbManager {
// Liste aller bekannten Accounts private HashMap <String,Account> accounts = new HashMap <String, Account>(); // DB-File private String dbfile="E:/temp/userdb.yap"; //Speichert einen Account public void save(Account a){ //Neue Configuration holen Configuration config = Db4o.newConfiguration(); // Configuration anpassen und cascadesOn<XY> setzen. // Sicherlich hier zu viel; aber erstmal zum Testen. config.objectClass(Account.class).cascadeOnUpdate(true); config.objectClass(Account.class).updateDepth(10); config.objectClass(Account.class).cascadeOnActivate(true); config.objectClass(java.util.HashMap.class).cascadeOnUpdate(true); config.objectClass(java.util.HashMap.class).updateDepth(10); config.objectClass(java.util.HashMap.class).cascadeOnActivate(true); config.objectClass(java.util.ArrayList.class).cascadeOnUpdate(true); config.objectClass(java.util.ArrayList.class).updateDepth(10); config.objectClass(java.util.ArrayList.class).cascadeOnActivate(true); // DB öffnen ObjectContainer db = Db4o.openFile(config,dbfile); try { // Die Accounts aus der DB laden. Dort muß der aktuelle Zustand // vorhanden sein. Es wird dort genau die Accounts geben, die // im System bisher bekannt sind. ObjectSet <HashMap> result = db.queryByExample(accounts); // Es darf nur ein Accounts-Objekt in der DB vorhanden sein! // Oder keines. Dann ist es der erste Aufruf. if (result.hasNext()){ accounts = result.next(); } // Ist der Account ein ganz neuer, oder bereits vorher // schonmal gespeichert worden? if (!a.isSaved()){ // Setze den Status auf gespeichert a.setSaved(); // Füge das Account-Objekt der zentralen Liste hinzu. accounts.put(a.getUsername(), a); } // Wenn der Account bereits in der DB vorhanden sein muß.... if (a.isSaved()) { // Username auslesen und anhand dessen, das eigentlich Objekt // in der DB finden String username = a.getUsername(); Account proto = new Account(username,null); ObjectSet <Account> resultaccounts = db.queryByExample(proto); Account resulta = null; if (resultaccounts.hasNext()){ resulta = resultaccounts.next(); // Das geladene Objekt mit den Werten des zu speichernden // Objektes füllen resulta.copyValuesFrom(a); } } // Speichern der Liste der Accounts db.store(accounts); // Was im Moment fehlt, ist die Prüfung, ob es nicht bereits einen Account // mit diesem Usernamen gibt. Später. } catch (DatabaseFileLockedException e) { e.printStackTrace(); } finally{ db.close(); } } // Läd einen Account anhand des Usernamens public Account load(String username){ //Neue Configuration holen Configuration config = Db4o.newConfiguration(); // Configuration anpassen und cascadesOn<XY> setzen. // Sicherlich hier zu viel; aber erstmal zum Testen. config.objectClass(Account.class).cascadeOnUpdate(true); config.objectClass(Account.class).cascadeOnActivate(true); config.objectClass(java.util.HashMap.class).cascadeOnUpdate(true); config.objectClass(java.util.HashMap.class).cascadeOnActivate(true); config.objectClass(java.util.ArrayList.class).cascadeOnUpdate(true); config.objectClass(java.util.ArrayList.class).cascadeOnActivate(true); // DB öffnen ObjectContainer db = Db4o.openFile(config,dbfile); // Prototypen definieren Account proto = new Account (username,null); Account a = null; try { // DB anhand des Prototypen durchsuchen ObjectSet <Account> result = db.queryByExample(proto); //Wenn es Ergebnisse gibt if (result.hasNext()){ a = result.next(); } } catch (DatabaseFileLockedException e) { e.printStackTrace(); } finally{ db.close(); } return a; } // Läd alle Accounts aus der DB in die HashMap public void loadFromDb() { //Neue Configuration holen Configuration config = Db4o.newConfiguration(); // Configuration anpassen und cascadesOn<XY> setzen. // Sicherlich hier zu viel; aber erstmal zum Testen. config.objectClass(Account.class).cascadeOnUpdate(true); config.objectClass(Account.class).cascadeOnActivate(true); config.objectClass(java.util.HashMap.class).cascadeOnUpdate(true); config.objectClass(java.util.HashMap.class).cascadeOnActivate(true); config.objectClass(java.util.ArrayList.class).cascadeOnUpdate(true); config.objectClass(java.util.ArrayList.class).cascadeOnActivate(true); // DB öffnen ObjectContainer db = Db4o.openFile(config,dbfile); try { ObjectSet result = db.queryByExample(accounts); if (result.hasNext()){ accounts = (HashMap) result.next(); } } catch (DatabaseFileLockedException e) { e.printStackTrace(); } finally{ db.close(); } } // Anzeige der Daten, die in der HashMap Accounts gespeichert sind. // Zu DEBUGING Zwecken public void view(){ Set <String> keys = accounts.keySet(); System.out.println("----------- List Of Accounts ------------"); for (String s: keys){ Account a = (Account) accounts.get(s); String username = a.getUsername(); String password = a.getPassword(); String history = ""; for (int i = 0;i < a.getHistory().size();i++){ history = history + a.getHistory().get(i); if (i + 1 < a.getHistory().size() ){ history = history + " | "; } } System.out.println("User: " + username + " - Password: " + password + " ("+history+")"); } } // Alle Objekte in der DB ausgeben. Zu DEBUGING Zwecken public void showDb() { ObjectContainer db = Db4o.openFile(dbfile); try { ObjectSet result = db.queryByExample(new Object()); for (Object o: result){ System.out.println(o.toString()); } } catch (DatabaseFileLockedException e) { e.printStackTrace(); } finally{ db.close(); } } }
--------------------------------------------------------------------------------------------------------------- public class _Demo { public static void main(String[] args){
// Manager erzeugen DbManager m = new DbManager(); // Alle Account-Daten aus der DB laden m.loadFromDb(); // Neuen Account erzeugen Account a1 = new Account("Dirk", "1234"); // den neuen Account speichern m.save(a1); // Einträge zur Kontraolle anzeigen m.view(); // den Account direkt aus der DB laden.... Account a2 = m.load("Dirk"); // ... und verändern a2.setPassword("2468122"); a2.addHistory("01.07.2008"); a2.addHistory("07.07.2008"); a2.addHistory("09.07.2008"); // Den geänderten Account wieder speichern m.save(a2); // Einträge zur Kontraolle anzeigen m.view(); // den Account wieder direkt aus der DB laden.... Account a3 = m.load("Dirk"); // ... und verändern a3.setPassword("2122"); a3.addHistory("01.08.2008"); // Den geänderten Account wieder speichern m.save(a3); m.showDb(); }
} Beim Durchlaufen gibt es folgende Ausgabe: ----------- List Of Accounts ------------ User: Dirk - Password: 1234 () ----------- List Of Accounts ------------ User: Dirk - Password: 2468122 (01.07.2008 | 07.07.2008 | 09.07.2008) ----------- List Of Accounts ------------ User: Dirk - Password: 2122 (01.07.2008 | 07.07.2008 | 09.07.2008 | 01.08.2008) {Dirk=com.tests.Account@1c247a0} com.db4o.config.Entry@d02b51 com.tests.Account@1c247a0 [01.07.2008, 07.07.2008, 09.07.2008] [] [01.07.2008, 07.07.2008, 09.07.2008, 01.08.2008]
Es kommt jetzt schonmal das richtige raus, aber die Liste wird mir zu oft als neu abgespeichert! Da müsste man jetzt wohl auch sagen, daß erst die ArrayListe geladen werden müsse. Aber ich kann doch nicht jedes Objekt einzeln rausfischen und erstmal laden lasen!? Ich dachte, dafür sind die cascadeOn<Irgendwas> da?!? Wird das nicht irgendwann super anstrengnend? Viele Grüße Fats
|
|
-
08-01-2008, 10:54 AM |
-
Origon45
-
-
-
-
Joined on 02-13-2008
-
Germany
-
Posts 97
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
fats:Es kommt jetzt schonmal das richtige raus, aber die Liste wird mir zu oft als neu abgespeichert!
Welche Liste meinst du jetzt genau? Die Historyliste oder die Hashmap? Ich würde das mit der Hashmap ganz raus lassen, ist meiner Meinung nach nicht wirklich nützlich und verwirrt dich nur. Fang am besten mit der Accountverwaltung ohne Hashmap an (wie ne normale DB) und versuche dich dabei am Tutorial (Ist in deinem Db4o Download enthalten.) zu orientieren. Dann kommst du sicher sehr schnell zu dem Punkt wo du strukturierte Objekte bekommst. Du baust dir also deine Manager auf, der Accounts speichern, updaten, auslesen, .... kann. Dann erweiterst du deine Objekte um die History und versuchst dich damit anhand des Buches oder des Tutorials vorran zu tasten.
Um das Prinzip mit dem cascadeOn<Irgendwas> zu verstehen solltest du zuerst die angegebene Literatur lesen, ist sehr aufschlussreich. Wenn dir Englisch nicht so liegt, kann ich dir dieses deutsche Buch empfehlen. http://developer.db4o.com/ProjectSpaces/view.aspx/Db4o-Book/Gesamt.Pdf
fats:Da müsste man jetzt wohl auch sagen, daß erst die ArrayListe geladen werden müsse. Aber ich kann doch nicht jedes Objekt einzeln rausfischen und erstmal laden lasen!? Ich dachte, dafür sind die cascadeOn<Irgendwas> da?!? Wird das nicht irgendwann super anstrengnend?
Du must nicht jedes Objekt einzeln laden, du kannst auch eine Abfrage über die ArrayListe machen. Wie oben geschrieben, empfehle ich dir, dir das Prinzip anzuschauen. Mfg Origon
Germany
|
|
-
08-01-2008, 11:31 AM |
-
fats
-
-
-
-
Joined on 07-28-2008
-
-
Posts 7
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
Origon45: fats:Es kommt jetzt schonmal das richtige raus, aber die Liste wird mir zu oft als neu abgespeichert!
Welche Liste meinst du jetzt genau? Die Historyliste oder die Hashmap?
Ups, sorry! Stimmt, sind ja jetzt zwei Listen! Mit dem jetzigen System wird die HashMap erfolgreich geschrieben. Das sieht soweit gut aus. Was ich jetzt hier meinte, ist die Historyliste (ArrayList). Wenn Du Dir die Ausgabe ansiehst, dann kommen in den letzten Zeilen direkt die Einträge aus der DB. Da gibt es die verschiedenen Stufen der History, die in der DB vorliegen. Das klingt danach, daß die ArrayList jedesmal als neues Objekt gespeichert wurde. Origon45: Ich würde das mit der Hashmap ganz raus lassen, ist meiner Meinung nach nicht wirklich nützlich und verwirrt dich nur. Fang am besten mit der Accountverwaltung ohne Hashmap an (wie ne normale DB)
Hmm .. ja gut. Ich kanns ja erst mal so probieren. Origon45: und versuche dich dabei am Tutorial (Ist in deinem Db4o Download enthalten.) zu orientieren.
Schon in weiten Teilen durchgearbeitet ;)
Origon45: Um das Prinzip mit dem cascadeOn<Irgendwas> zu verstehen solltest du zuerst die angegebene Literatur lesen, ist sehr aufschlussreich. Wenn dir Englisch nicht so liegt, kann ich dir dieses deutsche Buch empfehlen. http://developer.db4o.com/ProjectSpaces/view.aspx/Db4o-Book/Gesamt.Pdf
Jup, das kenn ich auch schon ;) Origon45: Du must nicht jedes Objekt einzeln laden, du kannst auch eine Abfrage über die ArrayListe machen. Wie oben geschrieben, empfehle ich dir, dir das Prinzip anzuschauen.
Hmm .. ich dachte eigentlich, ich hätte das soweit verstanden. Aber ich geh besser noch mal n Schritt zurück. Erstmal soweit einen herzlichen Dank! Viele Grüße Fats
|
|
-
08-01-2008, 12:54 PM |
-
Origon45
-
-
-
-
Joined on 02-13-2008
-
Germany
-
Posts 97
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
fats:Was
ich jetzt hier meinte, ist die Historyliste (ArrayList). Wenn Du Dir
die Ausgabe ansiehst, dann kommen in den letzten Zeilen direkt die
Einträge aus der DB. Da gibt es die verschiedenen Stufen der History,
die in der DB vorliegen. Das klingt danach, daß die ArrayList jedesmal
als neues Objekt gespeichert wurde.
Hm, vielleicht sind die Einträge noch im Cache, hab so ne Komplettausgabe noch nie gemacht. Um sicher zu gehen, kannst du doch einfach mal die DB nach jeder Aktion schließen oder commiten. Du kannst dir auch bevor du a2.addHistory machst, nochmal die History ausgeben lassen, oder du schaust einfach mal mit dem Objektmanager in die DB und dann müsstest du sehen, wie viele ArrayListen drin sind. fats: Hmm .. ich dachte eigentlich, ich hätte das soweit verstanden. Aber ich geh besser noch mal n Schritt zurück.
Das wird schon! :)
Germany
|
|
-
08-01-2008, 01:19 PM |
-
fats
-
-
-
-
Joined on 07-28-2008
-
-
Posts 7
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
(Ein paar Codezeilen später ....) So wie ich das im Moment sehe, ist mein ganzes Konzept mit dem Manger so in der Art nicht tragbar! All die Beispiele basieren darauf, daß nur zwischen dem db = Db4o.openFile(config,dbfile); und dem db.close(); Daten verändert werden! Bei mir werden die Daten bisher ja außerhalb dieses Blockes verändert! Als Lösungen sehe ich: a) ich verteile in meiner Anwendung überall, wo ich Daten verändern möchte, die "db = Db4o.openFile(config,dbfile); {....} db.close()" Blöcke
b) ich muß die save-Methode soweit aufbohren, daß sie den ganzen Objekt-Baum abläuft, die einzelnen Objekte läd, aktualisiert und dann neuspeichert. Ist der Gedanke so weit richtig?
Viele Grüße Fats
|
|
-
08-01-2008, 02:10 PM |
-
Origon45
-
-
-
-
Joined on 02-13-2008
-
Germany
-
Posts 97
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
Ich dachte du hattest das jetzt so gebaut, dass du die DB einmal öffnest und eigentlich nicht wieder zu machst, bis du deine Anwendung schließt. Weil so bist du doch wieder bei der Geschichte, DB öffnen und schließen kostet Zeit. Damit würde Methode a eigentlich rausfallen. Ich versuche dir das nochmal so zu erklären wie du es dir jetzt vorstellst. Du willst eine DB haben wo Accounts gespeichert sind. Du willst aber um keine unnötigen Ressourcen zu verschwenden, die DB so wenig wie möglich befragen bzw. belästigen. Hoffe das ist soweit richtig. :) Deshalb hältst du dir eine Hashmap im RAM wo du veränderungen vornimmst und diese meist auch nach Accounts abfragst. Immernoch Richtig? Wenn du das wirklich so implementieren willst, was ich nicht so machen würde :), dann musst du folgendermaßen vorgehen. 1. Die Hashmap beinhaltet Accounts. Du kannst die Hashmap außerhalb der DB frei verändern wie du möchtest, du kannst Accounts hinzufügen und ändern. Die Hashmap (Objektbaum) ist dann halt geändert im Ram enthalten, das spielt keine Rolle weil es immernoch ein Objektbaum Hashmap ist, der halt viele Account Objekte referenziert. Aufgabe von Db4o ist es ja nun solche Objektbäume zu speichern.
2. Irgendwann kommst du zu dem Punkt, wo du deine Daten in die DB sichern möchtest.(Vorher arbeitest du nur im RAM auf der Hashmap rum) Jetzt kommt eigentlich der Zeitpunkt wo du die Hashmap, samt Accounts, in die Datenbank speichern musst, oder die Hashmap updaten musst. Du brauchst also gar keine Verwaltung an sich für die Hashmap wenn du das so machst. Es sei denn, du willst dir halt noch Accounts einzeln von der DB abfragen, updaten, speichern. Aber für gewöhnlich würde man einfach eine DB-Verbingung öffnen und so lange seine Accounts in der DB verwalten (ohne Hashmap), bis das Programm zum Verwalten geschlossen wird. Grüße Origon
Germany
|
|
-
08-01-2008, 05:18 PM |
-
fats
-
-
-
-
Joined on 07-28-2008
-
-
Posts 7
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
Hi Origon, ich hab das jetzt erstmal so gemacht, wie Du es mir geraten hast: ohne Hashmap und ganz klein anfangen ;) Ich habe also alle Listen (hashmap plus history) rausgeworfen und teste erstmal mit kleinen Objekten und dem Manager rum :) Mittlerweile bin ich bei der Möglichkeit b) angelangt - a) hat mir irgendwie gar nicht gefallen ;) Beim Speichern muß man also beachten, daß man das "alte" Objekt läd und dort dann die neuen Werte manuell reinschreibt. Hat man Unterobjekte in der Struktur, so müssen diese sich auch einzeln die Werte neu zuweisen. Geht eigentlich soweit ganz gut. Versuche grade die save-Methode soweit aufzubohren, daß sie für verschiedene Objekte allgemeingültig wird. Das ist ganz schön nervig .. aber mal sehen ;)
Aber prinzipiell möchte ich schon irgendwann zu dem Punkt kommen, wo die Daten im RAM liegen und nur bei Bedarf mit der DB gesynct werden - das hast Du daher soweit schon richtig verstanden :) Aber dieses Ziel hab ich jetzt erstmal hinten angestellt. So wie Du es beschrieben hast, stelle ich mir das eigentlich im Idealfall vor: Hashmap mit den Objekten füllen, die Objekte jonglieren und wenn es soweit ist, die HashMap in die DB speichern, bzw. updaten. Aber wie gesagt, das ist erst der nächste Schritt ;)
Viele Grüße Fats
|
|
-
08-12-2008, 09:56 PM |
-
Peter Brightman
-
-
-
-
Joined on 08-31-2007
-
south germany
-
Posts 23
-
-
-
|
Re: Anfängerfrage - Vorgehensfrage
fats:Hi Origon, ich hab das jetzt erstmal so gemacht, wie Du es mir geraten hast: ohne Hashmap und ganz klein anfangen ;)
Ich finde das auch besser wenn Du auf die hashmap verzichtest, deswegen würde ich den Rat von Origon annehmen. Irgendwie bekommst Du glaube ich Probleme mit der Identity Deiner Objekte. fats: Beim Speichern muß man also beachten, daß man das "alte" Objekt läd und dort dann die neuen Werte manuell reinschreibt.
Das ist genau der Punkt. Das was Du als das "alte" Objekt bezeichnest ist halt ein Objekt mit einer gewissen Identität. Wenn Du die DB schließt und das Objekt im Hash oder sonstwo vorhältst, dann ist das eine Kopie des Objekts! Ich glaube hier gab es schon mal eine interessante Diskussion über Objektidentität. Da ging es auch um das committen transienter Objekte, hochinteressant. Kannst Du Dir vorstellen dass wenn Du Daten eines Objekts änderst es immer noch das gleiche Objekt ist? Deswegen musst Du wohl beim Speichern Deiner im Hash (RAM) geänderten Objekte Dein - wie Du sagst - altes bzw. Originalobjekt erst mal nach erneutem öffnen der db4o-DB wieder herholen, Werte aus Deiner Kopie zuweisen und dann das Original abspeichern. Das sollte funktionieren. Wenn Du es anderst machst hast Du dann wohl zwei Objekte gespeichert. Ist mir auch schon passiert, also nicht verzweifeln.
fats:Aber prinzipiell möchte ich schon irgendwann zu dem Punkt kommen, wo die Daten im RAM liegen und nur bei Bedarf mit der DB gesynct werden - das hast Du daher soweit schon richtig verstanden :) Aber dieses Ziel hab ich jetzt erstmal hinten angestellt. So wie Du es beschrieben hast, stelle ich mir das eigentlich im Idealfall vor: Hashmap mit den Objekten füllen, die Objekte jonglieren und wenn es soweit ist, die HashMap in die DB speichern, bzw. updaten. Aber wie gesagt, das ist erst der nächste Schritt ;)
Du kannst schon einen Cache implementieren, doch dann solltest Du die gesamte Hashtable abspeichern und vorher die alte löschen denke ich. Mit der richtigen Update-Depht werden dann die referenzierten Objekte eh mitgespeichert. Also da würde ich nicht die Hashtable sowie alle referenzierten Objekte abgleichen sondern die alte Hashtable löschen, dann neuere, aktuellere speichern. Bedenke dass sobald Du die Datenbank zumachst, Du immer nur mit Kopien der gespeicherten Objekte in der Datenbank weiterarbeiten kannst und wirst. Die Objekte in der Datenbank (persistenter Speicher) haben keine RAM-Adressen mehr!
Gruß,
~~pb~~~~~~~~~~~~~~
|
|
|
|
|