# [DB4O] Objekte sollen sich nicht verändern



## fkerber (11. Aug 2010)

Hi!

Ich habe folgendes Problem:
Ich erzeuge zur Speicherung von Sprach-Templates div. Datenstrukturen (Sentence, enthält Nouns,  Noun hat Adjectives etc.)
Jetzt speichere ich einen solchen Sentence in der DB - und zwar DB4O.
Das klappt auch soweit ganz gut - der Haken kommt beim rausnehmen und verarbeiten...

Ich ersetze Teile meiner Strukturen durch Nutzereingaben. Dummerweise verändert sich die Struktur dann auch in der DB.

Konkret mache ich folgendes:

```
private Template getTemplateByName(String templateName) {

		Query query = db.query();
		query.constrain(Template.class);
		query.descend("name").constrain(templateName).equal();

		ObjectSet<Template> result = query.execute();
		if (result.hasNext()) {
			Template x = result.next();
			System.out.println(x.getVariables().get(0).getWord()); // zur Visualisierung
			return x;
		} else {
			return null;
		}
	}
```

Ich nehme mir also so ein Template und verarbeite es dann:

```
var.getWord().setVariable("BliBlaBlub");
```


Jetzt brauche ich das selbe Template später nochmal (allerdings möchte ich dann anderen Inhalt reintun. Dieser Versuch offenbart aber ein essentielles Problem. Obiges Sysout liefert nämlich beim 2. Mal "BliBlaBlub" - also wurde das in der DB liegende Objekt "mitverändert" bzw. anders gesagt - es gibt nur ein Objekt...

Das ist leider für mich ein essentielles Problem und ich wäre für Lösungsideen dankbar.
Von einem CopyConstructor würde ich gerne absehen (wenn irgendmöglich), nämlich jetzt durch diese ganzen Strukturen durchzusteppen und da überall alles ordentlich zu kopieren wird sicherlich kein Spaß...

Daher hoffe ich, dass es da einen anderen Weg gibt?

Liebe Grüße,
fkerber


----------



## Gast2 (11. Aug 2010)

fkerber hat gesagt.:


> Das ist leider für mich ein essentielles Problem und ich wäre für Lösungsideen dankbar.
> Von einem CopyConstructor würde ich gerne absehen (wenn irgendmöglich), nämlich jetzt durch diese ganzen Strukturen durchzusteppen und da überall alles ordentlich zu kopieren wird sicherlich kein Spaß...
> 
> Daher hoffe ich, dass es da einen anderen Weg gibt?



Du müsstes soetwas nutzen: https://developer.db4o.com/Document...java/api/com/db4o/ext/ExtObjectContainer.html -> peekPersisted

Oder deine Object "cloneable" (evtl, Trick über serialisierung, such mal nach deep copy arraylist) machen. Und dann:

```
if (result.hasNext()) {
            Template x = result.next();
            System.out.println(x.getVariables().get(0).getWord()); // zur Visualisierung
            return x.clone();
        } else {
            return null;
        }
```


----------



## fkerber (11. Aug 2010)

Hi!

Danke für deine Antwort. Das erste werde ich mir mal anschauen.

Das zweite mit dem Clone ist ja das, was ich mit dem Copy-Constructor meinte. Ich müsste ja in all meinen Klassen dann Clone implementieren, um tatsächlich dann (quasi rekursiv) all meine Teilstrukturen zu clonen, damit da nirgendwo mehr Referenzgleichheit herrscht...

Liebe Grüße,
fkerber


----------



## Gast2 (11. Aug 2010)

fkerber hat gesagt.:


> Ich müsste ja in all meinen Klassen dann Clone implementieren, um tatsächlich dann (quasi rekursiv) all meine Teilstrukturen zu clonen, damit da nirgendwo mehr Referenzgleichheit herrscht...



Jein, kommt auf deine Objekte an. Wenn alle serialisierbar sind ist es recht einfach machbar: JavaTechniques  Faster Deep Copies of Java Objects


----------



## fkerber (11. Aug 2010)

Hi!

Das mit dem peekPersisted sieht schon sehr gut aus.
Es gibt nur noch ein kleines "Problem".
Eigentlich nutze ich TransparentActivation und das hat auch funktioniert bisher.
Hier muss ich ja jetzt explizit eine Tiefe angeben.

Ist es jetzt unschädlich, wenn ich da z.B. 100 angebe, um einfach auf Nummer sicher zu gehen oder sollte ich diesen Wert restriktiver gestalten? Also ich möchte immer das komplette Objekt laden (da ich es auch komplett brauche) - daher wäre die Frage, wenn restriktiver, wie ermittele ich den Wert korrekt. Also ich habe z.B. ein Objekt mit mehreren String-Feldern und einem Feld eines anderen Datentyps, dieser hat z.B. wieder drei ArrayLists als Felder, jeweils wieder von eigenen Datentypen usw.


Liebe Grüße,
fkerber


----------



## Gast2 (11. Aug 2010)

Du kannst die maximale Tiefe prinzipiell rekrusiv mit ein paar Tricks und Reflection ausrechnen. Aber ob das wirklich etwas bringt? Glaub ich kaum. 

Kennst du dein Datenmodell gut? Wie wahrschienlich ist eine Tiefe von mehr als 25? Bist du sicher das 100 immer die maximale Tiefe ist? 

Von der Performance her sollte es weitgehend egal sein da db4o ja eh nur so tief list wie er Referenzen finded. Das ist soweit ich weiß nur dazu da um Queries auf sehr komplexe Strukturen zu beschleunigen.


----------

