Search the FirstSpirit Knowledge Base
Hallo zusammen,
ich versuche, eine geordnete 1:N Beziehung in der Datenbank per API umzusortieren. Auf der "1"-Seite wird eine FS_LIST vom Typ "database" verwendet, um die Beziehungen zur "N"-Seite zu verwalten. Die FS_LIST ist mit dem Parameter "PERSISTENCEINDEX" versehen, um die Reihenfolge der Einträge zu speichern. Auf der "N"-Seite wird eine CMS_INPUT_COMBOBOX verwendet, um die Beziehung zur "1"-Seite zu verwalten.
Als Vorbereitung habe ich über den Java-Client eine Entität in der Master-Tabelle angelegt sowie 3 Entitäten in der Slave-Tabelle. Ebenfalls über den Java-Client habe ich die 3 Slaves mit dem Master verknüpft. Die Spalte, in der die Position der Slaves verwaltet wird ist nun wie folgt gesetzt:
slave_1 (ID 578) - Index: 0
slave_2 (ID 579) - Index: 1
slave_3 (ID 580) - Index: 2
Die Positionen werden sowohl in der Slave-Tabelle als auch in der FS_LIST der Master-Tabelle entsprechend angezeigt:
(Ansicht der Master-Entität in der Datenquelle "Master")
(Ansicht Slave-Entitäten in der Datenquelle "Slaves")
Nun starte ich auf der Master-Entität die Beanshell-Console und führe die folgenden Schritte aus, um slave_1 an die letzte Position zu verschieben:
context.storeElement.setLock(true, false);
masterEntity = context.selectedRow;
context.storeElement.lock(masterEntity);
masterDataset = context.storeElement.getDataset(masterEntity);
masterForm = masterDataset.getFormData();
masterFSList = masterForm.get(null, "tt_slaves").get();
Folgende Ausgabe für den Inhalt von masterFSList:
<[EntityFormData{_entity=de.espirit.or.impl.EntityImpl@c3ea3543{slave_1_n,PERSISTENT,FS_ID=578,FS_VALID_FROM=1336391930298,FS_VALID_TO=9223372036854775807,FS_RELEASE_TO=0}}, EntityFormData{_entity=de.espirit.or.impl.EntityImpl@c3eaa9a2{slave_1_n,PERSISTENT,FS_ID=579,FS_VALID_FROM=1336391930298,FS_VALID_TO=9223372036854775807,FS_RELEASE_TO=0}}, EntityFormData{_entity=de.espirit.or.impl.EntityImpl@c3eb1e01{slave_1_n,PERSISTENT,FS_ID=580,FS_VALID_FROM=1336391930298,FS_VALID_TO=9223372036854775807,FS_RELEASE_TO=0}}]>
Nun verschiebe ich slave_1 (ID 578) an die letzte Position der Liste:
slave1 = masterFSList.remove(0);
masterFSList.add(slave1);
Zur Kontrolle erneute Ausgabe des Inhaltes von masterFSList:
<[EntityFormData{_entity=de.espirit.or.impl.EntityImpl@c3eaa9a2{slave_1_n,PERSISTENT,FS_ID=579,FS_VALID_FROM=1336391930298,FS_VALID_TO=9223372036854775807,FS_RELEASE_TO=0}}, EntityFormData{_entity=de.espirit.or.impl.EntityImpl@c3eb1e01{slave_1_n,PERSISTENT,FS_ID=580,FS_VALID_FROM=1336391930298,FS_VALID_TO=9223372036854775807,FS_RELEASE_TO=0}}, EntityFormData{_entity=de.espirit.or.impl.EntityImpl@c3ea3543{slave_1_n,PERSISTENT,FS_ID=578,FS_VALID_FROM=1336391930298,FS_VALID_TO=9223372036854775807,FS_RELEASE_TO=0}}]>
slave_1 steht nun also am Ende.
Nun setze ich das geänderte FormData und entsperre den Datensatz:
masterDataset.setFormData(masterForm);
masterDataset.save();
context.storeElement.save();
context.storeElement.unlock(masterEntity);
context.storeElement.setLock(false, false);
Das Ergebnis im Java-Client ist nun erstaunlicherweise folgendes:
In der *Slave*-Tabelle wurden die Positionen entsprechend der Umsortierung aktualisiert:
(Ansicht Slave-Entitäten in der Datenquelle "Slaves")
In der Ansicht der FS_LIST in der Master-Tabelle stehen jedoch noch die *alten* Positionen (siehe oben). Außerdem habe ich folgende Beobachtungen gemacht:
Zunächst würde ich natürlich gerne wissen, wie ich vorgehen muss, damit die Positionen auch aus Sicht des Master-Datensatzes korrekt aktualisiert werden. Dann würde mich aber auch noch interessieren, wie der zuletzt beschriebene Zustand überhaupt entstehen kann. Der Java-Client zeigt ja hier zwei verschiedene Werte für jeweils das gleichen Datum an (?) Nach meinem Verständnis schlagen hier entweder Caches quer, oder die Slave-Positionen werden an zwei Stellen gespeichert (einmal in der FS_LIST und einmal in der Spalte der Slave-Tabelle). Sollte letzteres der Fall sein, ist aber die Frage, wie Beobachtung 2.) zu erklären ist.
Vielen Dank und viele Grüße,
Tilman Linden
Der Typ ist zwar eine Liste, aber da dies auf eine 1:N-Beziehung der Datenbank abgebildet wird, gibt es keine vorgegebene Ordnung. Man kann die Liste nach Werten der enthaltenen Elemente sortieren, das macht die API aber nicht automatisch.
Bei der Benuztung von FS_LIST kann man aber ein Sortierkriterium angeben. Wenn man über die API der FS_LIST geht, ist dann die Reihenfolge konsistent. Allerdings muss dann beim Umsortieren meistens auch mehr gespeichert werden.
Danke für die Antwort, leider hilft sie mir noch nicht weiter.
Ich verstehe Ihre Antwort so, dass zwischen den Werten, die in der mit "PERSISTENCEINDEX" angegebenen Spalte der "N"-Seite gespeichert sind, und der Reihenfolge der in der FS_LIST stehenden Datensätze kein Zusammenhang besteht. Das widerspricht jedoch meines Erachtens nach der Doku zu "PERSISTENCEINDEX":
"This tag can be used to save the ordering of elements which are selected in the FS_LIST if they are related to a 1:N foreign key.
For this purpose, FS_LIST must be defined in table template for a table which is related to a second table via a 1:N foreign key relation. This is necessary to ensure that one data set of the foreign key table will not be referenced more than once, because this would lead to an undetermined ordering. Thus, the first table is the source table (1 element), the second table the target table (N elements). FS_LIST must be mapped to the foreign key.
A column of the type Integer must be created in the target table in the related database scheme, in which the position of each element selected in FS_LIST will be stored. The name of this column must be given within an opening and a closing PERSISTENCEINDEX tag,"
Außerdem widerspricht es der Beobachtung, dass die über "PERSISTENCEINDEX" benannte Spalte in der Slave-Tabelle durch das in meinem Posting genannte Vorgehen aktualisiert wird, ohne das explizit in diese Spalte geschrieben wurde (also gibt es irgendeine Art von Zusammenhang zwischen der Reihenfolge der FS_LIST bzw. FormDataList und der Index-Spalte in der Slave-Tabelle). Die Frage bleibt: Warum werden die Werte in der Index-Spalte aktualisiert, ohne das dies einen Einfluss auf die Element der FS_LIST hat? (Mehr noch: Warum zeigen die Einträge in der FS_LIST in der benannten Spalte andere Werte, als eigentlich in der Datenquelle gespeichert sind?)
Es würde mich sehr freuen, wenn Sie mir hier ein klares Verständnis der zu Grunde liegenden Mechanismen vermitteln könnten. Nach der o. g. Doku gehe ich davon aus, dass "PERSISTENCEINDEX" das Mittel der Wahl ist. Wenn dem nicht so ist, würde ich gerne verstehen, warum, und wie alternativ vorzugehen ist.
EDIT: Hier noch die Definition der FS_LIST im Formular der Master-Tabelle
<FS_LIST name="tt_slaves">
<DATASOURCE type="database" useLanguages="no">
<ACTIONS>
<ACTION name="EDIT"/>
<ACTION name="ADD"/>
<ACTION name="REMOVE"/>
<ACTION name="DETACH"/>
<ACTION name="DOWN"/>
<ACTION name="UP"/>
</ACTIONS>
<COLUMNS>
<COLUMN show="no">#identifier</COLUMN>
</COLUMNS>
<LAYOUT>
<ADD component="overview" constraint="center"/>
<ADD component="toolbar" constraint="top"/>
<ADD component="tabbedview" constraint="hide"/>
</LAYOUT>
<PERSISTENCEINDEX>ix</PERSISTENCEINDEX>
<TABLE>global.slave_1_n</TABLE>
</DATASOURCE>
<LANGINFOS>
<LANGINFO lang="*" label="Slaves"/>
</LANGINFOS>
</FS_LIST>
Nein, das wollte ich nicht sagen. Sondern dass bei Änderung über die API die entsprechenden Indizes manuell geändert werden müssen.
Ok. Ausgehend von folgender Code-Sequenz (von oben übernommen):
context.storeElement.setLock(true, false);
masterEntity = context.selectedRow;
context.storeElement.lock(masterEntity);
masterDataset = context.storeElement.getDataset(masterEntity);
masterForm = masterDataset.getFormData();
masterFSList = masterForm.get(null, "tt_slaves").get();
slave1 = masterFSList.remove(0);
masterFSList.add(slave1);
masterDataset.setFormData(masterForm);
masterDataset.save();
context.storeElement.save();
context.storeElement.unlock(masterEntity);
context.storeElement.setLock(false, false);
An welcher Stelle und über welchen Aufruf wären jetzt die Indizes zu setzen?
die Daten (FormData) der zu N -Kante habe ein FormField<?> mit dem Bezeichner des PERSISTENCEINDEX, hier 'ix'.
Dieser Wert des FormField muss gesetzt werden.
bspw.
final FormField<?> field = formData.get(language, "ix");
field.set(index);