[GORM] Prüfen auf Änderung?

Dieser Bereich dient dazu, neue Features zu diskutieren und für die Entwicklung zu dokumentieren. // This area is dedicated to new features including proposals and documentation.
Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

[GORM] Prüfen auf Änderung?

Beitrag von MrNiceGuy » 01.11.2011, 08:24:16

Moin!

Bin gerade an einer Umsetzung im GORM, bei der über eine SOAP-Schnittstelle diverse Datensätze von einem Webservice ausgelesen und in die DB geschrieben werden sollen. Hierbei gibt es eine Abhängigkeit zwischen einem Datensatz und den ausgelesenen Daten, sodass ich mit addRelatedObject weitere Objekte anhänge und dann nach dem ersten Durchlauf mit saveObject() den Haupt-Datensatz speichere (also den, auf den sich die ausgelesenen Datensätze beziehen). Insgesamt muss ich eine variable Anzahl Shcleifendurchläufe tätigen, wodurch auch häufiger die Methode saveObject() aufgerufen wird. Jetzt habe ich mal den GORM grob überflogen und dabei festgestellt, dass bei saveObject() IMMER ein UPDATE oder INSERT ausgeführt wird, egal, ob dieser notwendig ist oder nicht.

Daher mal die Frage ganz allgemein: Wäre es nicht schneller eine Art Flag als private-Argument im GenericDomainObject zu speichern, das indiziert, ob eine Änderung durchgeführt wurde oder nicht? Dabei schwebt mir zum Beispiel folgendes vor: Wird ein GDO manuell erstellt ist der Wert immer auf TRUE, muss also gespeichert werden. Nach dem Aufruf von saveObject() würde dieses Flag dann auf FALSE gesetzt werden, bis irgendwann setProperty()/setProperties() aufgerufen wird.
Werden die Daten aus der DB ausgelesen müsste der Wert standardmäßig auf FALSE gesetzt sein, bis halt durch setProperty()/setProperties() wirklich Änderungen vorgenommen wurden.

Damit könnte man sich bei großen Bäumen eine Menge Queries sparen!?

Ideen? Vorschläge? Ergänzungen? Kritiken?
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4556
Registriert: 04.11.2007, 16:13:53

Re: [GORM] Prüfen auf Änderung?

Beitrag von dr.e. » 01.11.2011, 15:18:20

Hallo Lutz,

ein "dirty flag" wäre eine mögliche Lösung für dieses Problem. Allerdings kann dein GDO ja innerhalb der Session länger leben als nur über einen Request. Hier besteht dann wieder das Problem, dass nicht erkennbar ist, ob das "dirty flag" noch aktuell ist. Es kann a) entweder durch Serialisierung grundsätzlich verloren gehen und du stehst vor dem selben Problem oder b) der serialisierte Zustand kann in zwischen schon wieder verändert worden sein und du bekommst das nicht mit.

PHP hat hier leider den Nachteil, dass du nicht in einem Application-Server bist, der ein solches Objekt mit einem entsprechenden Status versehen kann.

Was du heute schon tun kannst ist, beim Speichern des aktuellen Objekts der saveObject()-Methode den optionalen Parameter mit "false" mitzugeben. Dann wird nur das eine Objekt gespeichert, nicht aber der komplette Baum. Dein Aufbau muss dann nur so sein, dass du immer dasjenige Objekt befüllst, das gespeichert werden soll und nicht dieses einem anderen mitzugeben.
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: [GORM] Prüfen auf Änderung?

Beitrag von MrNiceGuy » 01.11.2011, 16:10:21

Ähm, so ganz habe ich das jetzt nicht verstanden... Wenn es ein Attribut im GDO gibt wird das doch entsprechend bei De-/Serialisierung immer korrekt übersetzt so wie es gerade gesetzt ist!? Dass es zu Inkonsistenzen kommen kann, wenn ich ein Objekt in Prozess 1 lade, dann in Prozess 2 den selben Datensatz anpasse und speichere und dann in Prozess 1 speichere, würde in dieser Konstellation mit meinem Vorschlag der Inhalt aus Prozess 1 nicht übernommen werden. Andererseits hat dies aber den Vorteil, dass neue Daten nicht durch ältere Prozesse überschrieben werden und somit aktuellere Versionen der Daten mit eventuell veralteten wieder überschrieben werden!?

Dass es dann auch eine Methode oder Parameter geben müsste, um das Speicher zu erzwingen ist schon klar. Um abwärtskompatibel zu sein müsste ohnehin diese Funktion explizit eingestellt werden - wodurch es optional wäre und in diesem Fall eigentlich die angesprochenen Probleme belanglos macht - obwohl ich die Probleme noch nicht nachvollziehen kann (s.o.) ^^
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4556
Registriert: 04.11.2007, 16:13:53

Re: [GORM] Prüfen auf Änderung?

Beitrag von dr.e. » 05.11.2011, 10:47:29

Hallo Lutz,

Serialisierung/Deserialisierung sind nicht das Problem. Es geht vielmehr darum, dass - wie du schreibst - inkonsistente Daten entstehen können und bei einem Speichern nicht klar ist, was genau geändert wurde.

Nehmen wir an du hast zwei Benutzer deiner Webseite oder deiner Web-Applikation. Diese nutzen Informationen die in der Sesssion gespeichert werden, jedoch der Möglichkeit unterliegen, von beiden geändert zu werden. Der erste Benutzer ändert diese Inhalte nun und aktualisiert die Daten in seiner Session. Das Objekt besitzt nun ein "dirty flag" und könnte vom GORM als zu speichern erkannt werden, wenn die Struktur von der Applikation gespeichert wird. Der zweite Benutzer bekommt von der Änderung nichts mit und ändert auf seine Weise die Informationen und speichert auch. Dabei gewinnt der, der zuletzt speichert. Allerdings natürlich mit veralteten Daten, sofern der erste Benutzer Attribute geändert hat, die auch im Änderungsbereich des zweiten Benutzers lagen. Ob es hier nun ein "dirty flag" gibt oder nicht, hilft keinem der beiden.

Weiterhin haben wir folgendes Szenario:

Variante 1 (dirty flag "überlebt" Serialisierung/Deserialisierung):

Code: Alles auswählen

GDO erstellen         : $dirtyFlag = true
GDO laden             : $dirtyFlag = false
GDO in Session ablegen: $dirtyFlag = false
Variante 2: (dirty flag "überlebt" Serialisierung/Deserialisierung nicht):

Code: Alles auswählen

GDO erstellen         : $dirtyFlag = true
GDO laden             : $dirtyFlag = false
GDO in Session ablegen: $dirtyFlag = true
Betrachten wir Variante 1, so hast du bei einem Baum an GDOs ein "dirty flag" nach Serialisierung/Deserialisierung dabei und kannst ein UPDATE/INSERT vermeiden. Allerdings können sich die Daten in der Zwischenzeit schon wieder geändert haben und das "dirty flag" ist zwar richtig, es bräuchte jedoch ein Merge der neuen Daten zu den geänderten. Und das kann - sofern es die gleichen Attribute im Objekt sind, die geändert wurden - zu Konflikten führen. In Variante zwei hast du zwar den Merge-Konflikt nicht, jedoch verlierst du den Änderungsstatus des Objekts.

Verstehst du die Problemstellung jetzt?

Sicher würde ein "dirty flag" die Möglichkeit einräumen, die Änderungen an einem GDO zu tracken und im Update-Statement nur diejenigen Attribute zu inkludieren, die auch relevant sind, es wirft aber auch neue Probleme auf.
Viele Grüße,
Christian

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: [GORM] Prüfen auf Änderung?

Beitrag von Screeze » 05.11.2011, 12:55:42

Soweit ich das verstehe ändert sich durch das dirty Flag aber nicht wirklich etwas, oder?
Denn die Problematik von in Session gespeicherten - veralteten Daten die dann womöglich in die DB geschrieben werden besteht ja so auch schon.

APFelsahne
Beiträge: 222
Registriert: 18.03.2010, 13:13:07
Wohnort: Ludwigshafen am Rhein
Kontaktdaten:

Re: [GORM] Prüfen auf Änderung?

Beitrag von APFelsahne » 05.11.2011, 13:26:49

ich meine auch, wie screeze, dass die problematik generell vorhanden ist. die problematik liese sich nur mit einem komplexen vergleichssystem zum teil lösen.
im endeffekt verhält es sich ähnlich zu subversion-problematik. wenn zwei oder mehr personen am selben datensatz arbeiten, lässt sich noch auf komplexe oder aufwändige weise prüfen ob die selben daten oder unterschiedliche bearbeitet wurden. bei letzteres findet noch ein merge statt. aber sollten die selben daten bearbeitet worden sein, stellt sich die frage, welche daten genommen werden sollen. hier muss also eine nachfrage an die betroffene person bzw betroffenen personen gestellt werden. das lässt sich aber auf der direkten eben des gorm nicht lösen.

imo ist es letztlich die aufgabe der konkreten anwendung, diese fälle bestmöglichst abzuhandeln, denn der gorm sollte sich dafür nicht interessieren.
Grüße, Florian
BildAPF-Extension wsCatalyst

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: [GORM] Prüfen auf Änderung?

Beitrag von MrNiceGuy » 05.11.2011, 14:01:59

Danke, Screez, das war es, was ich versuchte Christian klar zu machen.

Die Problematik ist mir bekannt, aber sie existiert jetzt ja schon. Einzig was ich gerne geändert hätte wäre die Tatsache, dass geladene Daten nur dann ein Update in der Datenbank erzeugen, wenn auch wirklich Änderungen durchgeführt wurden. Im Bezug auf deine Beispiele, Christian, bedeutet das jedoch eine verringerung der Problematik, denn:

Angenommen beide User arbeiten gleichzeitig und haben sich den gleichen Stand aus der DB gezogen und beide speichern die Daten in der Session. Nun ändert User 1 etwas und verlässt den Bereich der Software, die für diese Daten relevant ist, wodurch die Software eine Speicherung veranlasst. User 2 bleibt noch ein wenig, ändert aber nichts an den Daten. User 2 hat zu diesem zeitpunkt inkonsistente Daten - keine Frage. Beim Verlassen des Bereiches wird auch hier eine Speicherung ausgeführt und überschreibt mit den alten Daten die bereits neu eingetragenen von User 1. mit dem Flag wie ich es mir vorstelle würde keine Speicherung von User 2 erfolten, weil dieser keine Änderung vorgenommen hat.

Verstehst du nun, wie ICH das meine? :)
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: [GORM] Prüfen auf Änderung?

Beitrag von MrNiceGuy » 05.11.2011, 14:05:45

@APFelsahne: Das stimmt, der GORM muss das nicht zwangsläufig abfangen und eine automatische Lösung dieser Problematik ist auch so nicht gewollt. Es würde aber schon helfen, wenn unveränderte Daten kein Update in der DB verursachen würde - mal abgesehen davon, dass es unnötige DB-Last bedeutet Updates auszuführen, die unnötig sind.

Um noch einen Schritt weiter zu gehen könnte ja nicht nur einfach der Aufruf von setProperty() zu einem Setzen des Flags führen, sondern vorher noch ein Abgleich der vorhandenen und der neuen Daten stattfinden, sodass auch nur bei einer wirklichen Änderung etwas passiert. Ich denke da z.B. an ein Import-Script von einer XML-Quelle, das würde die Prüfung der Daten innerhalb der Anwendung selbst jedenfalls überflüssig machen!?
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4556
Registriert: 04.11.2007, 16:13:53

Re: [GORM] Prüfen auf Änderung?

Beitrag von dr.e. » 05.11.2011, 23:20:47

So gesehen muss ich euch Recht geben. :? :roll: Wer macht einen Vorschlag (Proposal) für die Änderung?
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: [GORM] Prüfen auf Änderung?

Beitrag von MrNiceGuy » 05.11.2011, 23:33:01

So wie ich es sehe gäbe es zwei Möglichkeiten der Implementierung:

1) Es gibt nur EIN Flag, das angibt, ob das gesamte Objekt gespeichert werden muss (also alle Properties) oder

2) Ein Array mit je einem Flag je Feld, sodass das Update sich auch nur auf die Felder bezieht, die geändert wurden.

Lösung 1 solte relativ leicht zu implementieren sein, wohingegen Lösung 2 ein wenig Arbeit bei der Erstellung des Update-Queries nach sich ziehen würde.

Alternativ wäre es ja auch denkbar eine erneute Abfrage des Datensatzes zu machen, bevor gespeichert wird, allerdings ginge hier dann der Vorteil des nicht weiter benötigten Updates teilweise verloren. Dafür würde man die Möglichkeit gewinnen den GORM mit zusätzlichen Funktionen auszustatten wie "Update nur wenn Daten konsistent" oder dergleichen.

Wie dem auch sei, mein Vorschlag wäre entweder ein einzelnes Flag (Lösung 1) oder eben ein Array (Lösung 2) anzulegen (private), das standardmäßig auf TRUE gesetzt wird. Werden Daten aus der DB gelesen wird das Flag auf FALSE gesetzt. Erfolgt eine Anpassung der Properties durch setProperties() bzw. setProperty() wird das Flag auf TRUE gesetzt. optional könnte an dieser Stelle eine Präfung erfolgen, ob der Inhalt sich auch geändert hat und nur in diesem Fall das Flag auf TRUE setzen.
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4556
Registriert: 04.11.2007, 16:13:53

Re: [GORM] Prüfen auf Änderung?

Beitrag von dr.e. » 06.11.2011, 13:32:57

Hallo Lutz,

ich würde zunächst Variante 1 umsetzen und ohne erneutes Lesen vor dem Update bzw. einer Prüfung auf Änderung bei set*(). Prämisse muss jedoch sein, dass das Domänen-Objekt-Feature weiterhin funktioniert und ein save dort ebenfalls zu keinem Update führt, wenn das "dirty flag" auf false steht.
Viele Grüße,
Christian

Megger
Beiträge: 1233
Registriert: 04.11.2008, 10:57:37

Re: [GORM] Prüfen auf Änderung?

Beitrag von Megger » 08.11.2011, 11:35:49

Hi

Wäre es in der Hinsicht vielleicht auch irgendwie lösbar eine ID anzugeben unter der das Object gespeichert werden soll?
Momentan habe ich den GenericORRelationMapper so umgeschrieben, dass saveObject noch einen dritten Parameter bekommt, nämlich die ID zum Speichern. Diese ID kann ich natürlich nicht direkt in das GenericDomainObject einbauen, da der GORM ein Update machen würde anstatt ein Insert.

Hintergrund ist der, dass ich momentan Daten zwischen verschiedenen Systemen übertrage und da gibt es auch Beziehungen zwischen den Objekten untereinander. Ich würde ungern noch ein extra Feld einführen, nur damit ich die "alte" ID noch gespeichert habe.

Aber so einfach ist es wahrscheinlich nicht möglich, da der GORM ja momentan anhand der ID entscheidet, ob ein Update oder ein Insert durchgeführt wird. Diese Entscheidung müsste dann mithilfe des Flags geschehen, wobei das Flag nicht nur true/false als Status haben müsste, sondern noch soetwas wie "IchBinKomplettNeuUndNochNichtInDerDatenbank".

Oder eine weitere Möglichkeit wäre, dass man das Verhalten von außen beeinflussen kann und diese Beeinflussung auch Priorität hat.

Code: Alles auswählen

$oUser = new GenericDomainObject('User');
$oUser->setProperty('UserID', 5);

// Es wird ein Update durchgeführt
$gorm->saveObject($oUser);
 

Code: Alles auswählen

$oUser = new GenericDomainObject('User');
$oUser->setProperty('UserID', 5);
$oUser->doInsert(true);

// Es wird ein Insert durchgeführt
$gorm->saveObject($oUser);
 
Der Nachteil des ganzen ist allerdings, dass der GORM nicht mehr selber entscheidet, was zu tun ist. Bei meiner momentanen Lösung wird nur das InsertStatement beeinflußt, sodass das Objekt unter einer bestimmten ID gespeichert wird.
Auch bei der Flag Variante gibt es diesen Nachteil.


Und zum Thema :D
Ich würde auch Variante 1 vorschlagen. Bei Variante 2 kann es dazu kommen, dass Prüfen und Zusammenbauen des Statements im Endeffekt wieder genauso langsam bist wie zu dem Zeitpunkt als einfach alle Statements an die Datenbank geschickt wurden.
Aber die Idee finde ich gut und ich kann mir vorstellen, dass dies
1. einiges an Geschwindigkeit für die gesamte Applikation herausholt
2. die Log Dateien für die Datenbank Queries übersichtlicher werden
Tutorial: Browsergame mit dem APF (Die ersten Parts handeln von Installation und Inbetriebnahme des APFs, deswegen sicherlich auch für alle Nicht-Browsergame-Programmierer interessant)

APF-Version
  • Entwicklung: 2.0
  • Produktiv: 1.15

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: [GORM] Prüfen auf Änderung?

Beitrag von MrNiceGuy » 09.11.2011, 10:30:33

Alternativ dazu könnte man statt eines UPDATE ein REPLACE INTO machen, allerdings sorgt das bei vielen Änderungen an Datensätzen zu einer Verwurstellung der Datenbank, was eine Optimierung in regelmäßigen Abständen nötig machen könnte.

In meinen Augen verhält sich der GORM vollkommen korrekt, denn es macht wenig Sinn eine ID vorzugeben, das widerspricht der Funktion eine PKs mit AUTO-INCREMENT.
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Megger
Beiträge: 1233
Registriert: 04.11.2008, 10:57:37

Re: [GORM] Prüfen auf Änderung?

Beitrag von Megger » 09.11.2011, 11:20:59

In meinen Augen verhält sich der GORM vollkommen korrekt, denn es macht wenig Sinn eine ID vorzugeben, das widerspricht der Funktion eine PKs mit AUTO-INCREMENT.
Im Grunde genommen hast du Recht, allerdings kann es auch Sinn machen die IDs zu vergeben (wie in meinem Fall bei der Datenmigration bzw. der Übertragung der Daten zwischen verschiedenen Systemen). Bei neuen Daten greift natürlich der PK mit Autoincrement.
Tutorial: Browsergame mit dem APF (Die ersten Parts handeln von Installation und Inbetriebnahme des APFs, deswegen sicherlich auch für alle Nicht-Browsergame-Programmierer interessant)

APF-Version
  • Entwicklung: 2.0
  • Produktiv: 1.15

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: [GORM] Prüfen auf Änderung?

Beitrag von MrNiceGuy » 09.11.2011, 14:14:46

Nutzt du den GORM für die Portierung von Daten auf andere Systeme? :|
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Gesperrt

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast