Eine Tabelle - mehrere unabhängige Arbeitsbereiche: Oracle Workspace Manager

Stellen Sie sich vor ...

  • Sie könnten eine Tabelle in einer APEX-Anwendung über einen längeren Zeitraum verändern (INSERT, UPDATE, DELETE)
  • Diese Änderungen erfolgen mit normalen APEX-Formularen - in der Datenbank findet also stets das COMMIT statt ...
  • ... und dennoch sind diese Änderungen nur für Sie sichtbar .
  • Und am Ende können Sie den Änderungsblock als Ganzes verwerfen oder für alle sichtbar machen.

Geht nicht? Geht doch! Mit dem Oracle Workspace Manager ist das möglich. Dieser Tipp baut auf dem bereits veröffentlichten ersten Teil zum Thema auf. Dort wurde der Workspace Manager beschrieben und Sie haben erfahren, wie Sie ihn in APEX-Anwendungen nutzen können (Abbildung 1).

Workspace Manager und APEX: in Aktion
Abbildung 1: Workspace Manager und APEX: in Aktion

Workspace-Manager und "Konflikte"

In diesem Tipp geht es um Konfliktsituationen und wie der Workspace Manager damit umgeht. Nun erzeugen wir eine solche Konfliktsituation: Wechseln Sie -ausgehend vom Ergebnis des ersten Teils in den LIVE Workspace und ändern Sie in einer Zeile etwas. Setzen Sie bspw. das Gehalt (SAL) von SMITH (EMPNO 7369) auf 5000. Wechseln Sie danach in einen anderen Workspace (TRANS_1) und ändern Sie das Gehalt von SMITH dort in 6000. Klicken Sie in beiden Fällen auf die Formular-Schaltfläche Änderungen anwenden.

Versuchen Sie nun, den Workspace TRANS_1 in den LIVE-Workspace zu "mergen" (Schaltfläche Merge WS). Sie werden eine Fehlermeldung wie in Abbildung 2 bekommen.

Fehlermeldung beim Merge Workspace: Konflikte erkannt
Abbildung 2: Fehlermeldung beim Merge Workspace: Konflikte erkannt

Sie haben eine Konfliktsituation erzeugt, in dem Sie ein- und denselben Datensatz sowohl im Parent- (LIVE) als auch im Child-Workspace (TRANS_1) geändert haben. Der Workspace Manager kann nicht alleine entscheiden, welche Variante beim Merge Workspace verworfen oder angenommen werden soll. Der Entwickler (oder der Anwender) muss diese Entscheidung treffen. Im folgenden werden Sie erfahren, wie Sie die APEX-Anwendung um ein entsprechendes Konfliktmanagement erweitern. Natürlich gibt es auch die Möglichkeit, ein generisches Konfliktmanagement einzurichten (bspw. immer den Child-Workspace verwerfen); dies muss jedoch mit PL/SQL-Code implementiert werden.

Exception der Merge Workspace-Operation abfangen

Zunächst werden wir den in Abbildung 2 dargestellten Fehler richtig abfangen - so dass die dort gezeigte Fehler-Seite nicht mehr auftaucht. Navigieren Sie zur Seite 0 und fügen Sie der Region ein neues Element namens P0_MESSAGE hinzu. Setzen Sie es auf ständig auf Read Only (Abbildung 3) und platzieren Sie es an einer geeigneten Stelle - hier werden wir künftig das Ergebnis der Workspace-Manager-Operationen anzeigen.

Read Only-Eigenschaften des Elements "P0_MESSAGE"
Abbildung 3: Read Only-Eigenschaften des Elements "P0_MESSAGE"

Gehen Sie nun zu den Anwendungsprozessen , dort zum beim letzten Mal erstellten Prozeß Merge Workspace und ändern Sie den PL/SQL-Code wie folgt.

begin
  dbms_wm.mergeWorkspace(
    workspace => :P0_EXISTING_WS
  );
 :P0_MESSAGE := 'MERGE Workspace erfolgreich';
exception
  when others then 
    if sqlcode = -20055 then 
      :P0_MESSAGE := 'Konflikte beim MERGE Workspace - Bitte zur Konfliktlösung navigieren';
    else 
      :P0_MESSAGE := sqlerrm;
    end if;
end;

Versuchen Sie die "Merge Workspace"-Operation anschließend nochmal. Sie sollten dann das in Abbildung 4 dargestellte Ergebnis bekommen.

Abgefangene Fehlermeldung beim "Merge Workspace"
Abbildung 4: Abgefangene Fehlermeldung beim "Merge Workspace"

Analog dazu können Sie nun auch die anderen Anwendungsprozesse mit entsprechenden Exception-Handlern und Erfolgsmeldungen ausstatten. Danach geht es daran, die Seite zur Konfliktlösung zu erstellen.

Konfliktlösung implementieren

Fügen Sie Ihrer Anwendung nun eine neue Seite hinzu. Nennen Sie diese Konfliktlösung und lassen Sie sie vorerst leer.

Der Workspace-Manager stellt spezielle Views bereit, aus denen die Details der Konfliktsituation hervorgehen. Diese Views tragen den Namen "{Tabellenname}_CONF". Für die Tabelle EMP lautet der Name der Konflikt-View also EMP_CONF. Diese testen wir nun zuerst im SQL Workshop. Setzen Sie zunächst das folgende kurze PL/SQL ab, um den richtigen Workspace einzustellen (wenn Sie andere Workspace-Namen verwendet haben, passen Sie entsprechend an) ...

begin
  dbms_wm.setConflictWorkspace('TRANS_1');
end;

... und anschließend selektieren Sie die View EMP_CONF (Abbildung 5).

Konfliktdetails in der View "EMP_CONF"
Abbildung 5: Konfliktdetails in der View "EMP_CONF"

Die View zeigt Ihnen für jede Zeile die Basisversion (WM_WORKSPACE = 'BASE') und die Versionsstände des Parent- und Child-Workspace (hier LIVE als Parent und TRANS_1 als Child).

Diese Daten werden Sie als nächstes als interaktiven Bericht auf der APEX-Seite zur Konfliktlösung darstellen. Neben den reinen Daten werden aber noch Checkboxen zur Auswahl einer Version (die konkrete Konfliktlösung) und eine zusätzliche Spalte zur Sortierung hinzugefügt (die Basis-Version sollte stets zuerst erscheinen). Navigieren Sie also zurück zu soeben erstellten neuen Seite und erstellen Sie dort einen neuen interaktiven Bericht mit folgender SQL-Abfrage:

select 
 case 
   when wm_workspace = 'BASE' then null
   else apex_item.checkbox(1, empno || '-' || wm_workspace)
 end as chosen_version,
 empno || '_' || decode(wm_workspace, 'BASE', '0', '1') sort,
 wm_workspace,
 empno,
 ename,
 job,
 mgr,
 hiredate,
 sal,
 comm,
 deptno,
 wm_deleted
from emp_conf
order by sort

Die Spalte SORT stellen Sie am besten auf Hidden (Versteckt); sie wird nur zur Sortierung benötigt. Mit der PL/SQL-Funktion APEX_ITEM.CHECKBOX generieren Sie die Checkboxen in die Berichtsausgabe. Zusätzlich müssen Sie, wie bereits vorhin im SQL Workshop den Conflict Workspace setzen. Fügen Sie der Seite also noch einen onLoad-Prozeß (beim Laden der Seite) namens Workspace setzen mit folgendem PL/SQL-Code hinzu.

begin
  dbms_wm.setConflictWorkspace(:P0_EXISTING_WS);
end;

So kann die bereits auf Seite 0 bereitgestellte Auswahlliste der existierenden Workspaces auch für die Auswahl des "Conflict Workspace" verwendet werden. Starten Sie die Seite, wählen Sie den Child-Workspace TRANS_1 aus der Auswahlliste aus und klicken Sie auf Workspace wechseln. Sie sollten dann ein Ergebnis wie in Abbildung 6 sehen.

Konfliktdetails als APEX-Anwendungsseite
Abbildung 6: Konfliktdetails als APEX-Anwendungsseite

Mit den Checkboxen vor den Berichtszeilen kann der Anwender sich für eine der Varianten entscheiden. Zur Anwendung dieser Auswahl und damit zur Konfliktlösung fügen Sie nun noch eine Schaltfläche (RESOLVE) hinzu. Die Schaltfläche soll die Seite weiterleiten (Submit) und anschließend auf die schon im ersten Tipp erstellte "Hauptseite" verzweigen.

Die eigentliche Konfliktlösung wird von einem PL/SQL-Prozeß gemacht. Erzeugen Sie also einen neuen Prozeß vom Typ PL/SQL, der bei Weiterleitung der Seite (onSubmit) ausgeführt wird und hinterlegen Sie den folgenden PL/SQL-Code:

declare
  v_line     varchar2(32767);
  v_pk       varchar2(4000);
  v_ws       varchar2(4000);
  v_keep     varchar2(6);
begin
  -- Konfliktlösung für den ausgewählten Workspace starten ...
  dbms_wm.beginresolve(:P0_EXISTING_WS);

  -- In APEX_APPLICATION.G_F01 befinden sich die angeklickten
  -- Checkboxen im Format {EMPNO}-{WORKSPACE}
  for i in apex_application.g_f01.first..apex_application.g_f01.last loop
    v_line := apex_application.g_f01 (i);
    -- EMPNO extrahieren
    v_pk := substr(v_line, 0, instr(v_line, '-') - 1 );
    -- Workspace extrahieren
    v_ws := substr(v_line, instr(v_line, '-') + 1);
   
    -- Feststellen, ob Workspace der Parent- oder Child Workspace ist
    if v_ws = :P0_EXISTING_WS then
      v_keep := 'CHILD';
    else 
      v_keep := 'PARENT';
    end if;

    -- Konflikt lösen
    dbms_wm.resolveConflicts(
      workspace    => :P0_EXISTING_WS,
      table_name   => 'EMP',
      where_clause => 'EMPNO = '||v_pk,
      keep         => v_keep
    );
  end loop;

  -- Wichtig: COMMIT in der Datenbank
  commit;
 
  -- Konfliktlösung abschließen
  dbms_wm.commitresolve(:P0_EXISTING_WS);
  
  :P0_MESSAGE := 'Konflikte erfolgreich bearbeitet';
end;

Zunächst wird die Konfliktbearbeitung mit DBMS_WM.beginResolve begonnen. Im Array APEX_APPLICATION.G_F01 befinden sich alle angeklickten Checkboxen. Der Inhalt ist dabei stets im Format '{EMPNO}-{Workspace}'; dies ergibt sich aus der SQL-Abfrage des Berichts - achten Sie auf den Aufruf von APEX_ITEM.CHECKBOX. So bekommt der Prozeß zu jeder EMPNO die Information, welcher Workspace die angenommene Version enthält. Mit dieser Information wird nun die PL/SQL-Funktion DBMS_WM.resolveConflicts aufgerufen. Da diese als Parameter die Werte "PARENT" bzw. "CHILD" anstelle der Workspace-Namen erwartet, muss (anhand des Workspace-Namens) erstmal festgestellt werden, ob der angenommene Workspace eben der Parent- oder Child-Workspace ist.

Nachdem alle Konflikte gelöst sind, muss zwingend ein COMMIT erfolgen und abschließend wird die Konfliktbearbeitung mit DBMS_WM.commitResolve beendet.

Stellen Sie schließlich noch bei den Bedingungen sicher, dass der Prozeß nur bei Klick auf die vorher erstellte Schaltfläche RESOLVE ausgeführt wird.

Anschließend können Sie die Konfliktbearbeitung testen. Starten Sie die Seite, markieren Sie eine der beiden Zeilen (Workspace LIVE oder TRANS_1) und klicken Sie auf die Schaltfläche Konflikte lösen (RESOLVE)...

Konfliktbearbeitung: Auswahl einer Version
Abbildung 7: Konfliktbearbeitung: Auswahl einer Version

... woraufhin Sie die ausgewählte Version in beiden Workspaces finden. Der Konflikt wurde gelöst.

Konflikte erfolgreich bearbeitet
Abbildung 8: Konflikte erfolgreich bearbeitet

Weitere Informationen zum Workspace Manager finden Sie hier:

Zurück zur Community-Seite