|
Letzte
Bearbeitung dieses Dokuments: |
Voraussetzungen für das Verständnis dieses Dokuments:Grundkenntnisse in
der Programmierung von Java (Klassen, Methoden,
Schleifen). |
Ungefährer Zeitbedarf zum Durcharbeiten dieses Dokuments:Arbeitszeit:
Für das Implementieren komplexerer Abfragen hängt der Arbeitsaufwand stark von der Aufgabe und der Routine ab. Eine Schätzung des Zeitaufwandes kann in diesen Fällen nicht gegeben werden. |
Dieses Dokument enthält Code-Muster für eine einfache Server-Side-Klasse eines BO (Business-Object) und Erweiterungen, die entsprechend den jeweiligen Anforderungen zusätzlich implementiert werden können.
Einfacher
Muster-Code für ein BOS
Muster-Code
für ein BOS bei Verwendung der Datenbank-Tabelle
'Parameter'
Anleitung
zur Adaptierung
* Änderung
des Namens der Java-Packages der Anwendung
* Adaptieren
des Kommentars
* Änderung
des Namens der Klasse und der 'Constructor'-Methoden
* DBA-Objekt
als Variable definieren
* Methode
setDBAAttributes(...)
adaptieren
* Methode
store()
adaptieren
* Methode
store()
adaptieren bei Verwendung
des JSBS_Parameter_DBA
* Methode
selectByUserKnownKey(...)
adaptieren
* Methode
selectByUserKnownKey(...)
adaptieren bei Verwendung
des JSBS_Parameter_DBA
* Methoden
selectNext(...)
und selectPrevious(...)
adaptieren
* Methoden
selectNext(...)
und selectPrevious(...)
adaptieren bei Verwendung
des JSBS_Parameter_DBA
* Methode deactivate()
adaptieren
* Methode isReferenced()
adaptieren
Zusätzlicher
Code in der EJB-Klasse (bei Client/Server Anwendungen)
Spezieller
Muster-Code
*
Prüfen auf Konsistenz der Werte dieses BO
*
Lesen von Attributswerten von anderen Datenbank-Tabellen -
Methode mergeVariablexy
Weitere Schritte und verwandte Dokumentation
Der Code für die
Server-Side-Klasse eines BO ist wesentlich umfangreicher als die
beiden anderen Klassen (Generelle Klasse bzw. Client-Side-Klasse) für
ein BO oder die Klasse für ein DBA.
Die hohe Zahl der
Anweisungen ist dadurch bedingt, dass verschiedene 'Constructor's und
Methoden mit Service-Funktionen für die Verbindung zur Datenbank
in jeder BOS-Klasse notwendig sind und diese nicht von einer
Basisklasse geerbt werden können – obwohl der Code für
jede BOS-Klasse gleich ist.
Das 'Erben' dieser Methoden von einer
Basisklasse wird verhindert, weil Java nur erlaubt, von einer
Basisklasse zu 'erben'.
Das ist durchaus sinnvoll weil sonst bei
anderen Konstellationen Zweideutigkeiten auftreten würden –
bei der Implementierung von BOS-Klassen aber ein Nachteil.
Für den
Muster-Code des JavaScout Fat-Client-Framework (JS-FCF) wurde
entschieden, dass die BOS-Klasse von der zugehörigen
(Generellen) BO-Klasse erbt.
Die Entscheidung basiert auf
Überlegungen zur Qualität und zum Arbeitsaufwand weil die
wesentlichen 'Eigenschaften' des BO (Geschäfts-spezifische
Variablen und eventuell Konstante Werte) nur in der Generellen
BO-Klasse festgelegt werden müssen.
Die sich für
jedes BOS wiederholenden Code-Teile beanspruchen zwar viel Platz im
Muster-Code, können aber durch Kopieren des Muster-Codes und mit
wenig Adaptionen für jede BOS-Klasse verwendet werden.
Die
höhere Anzahl von Zeilen ist für die Laufzeit kein Nachteil
weil der Compiler eine Optimierung durchführt.
Und wenn Sie die
Erkärungen in dieser Vorbemerkung nicht ganz verstanden haben
ist das auch kein Hindernis für das Codieren von BOS.
Für
eine umfangreichere Erklärung bemühen Sie bitte eine
Internet-Suchmaschine mit den Begriffen 'Java Mehrfachvererbung' ;-).
Tutorial für die Programmierung eines Heavyweight-Clients (Fat-Client) durchgearbeitet.
Datenmodell fertig ausgearbeitet.
Generelle Klasse für das BO erstellt; siehe Muster-Code für ein BO (Generelle Klasse eine Business-Object).
Welche Platzhalter
durch Bezeichnungen des eigentlichen Projektes zu ersetzen sind
finden Sie im Abschnitt
Anleitung
zur Adaptierung.
package
application_package
.bos;
/*
*
Package für die Verbindung zur Datenbank. */import
java.sql.*;
/*
Java-interne Klasse für ein Datum; benötigt für
Umwandlung des Datums
* in die Klasse aus der
Bibliothek 'java.sql'. */import
java.util.Date;
/*
*
Basis-Klasse mit unterstützenden Methoden für die
Verarbeitung von BO. */import
js_base.bo.*;
/*
Basis-Klasse mit dem Minimalen Set an Parametern. Diese enthalten das
Arbeitsdatum.
* Das Arbeitsdatum wird für
verschiedene Abfragen gebraucht. */import
js_base.structures.JSBS_MinimalParameters;
/*
*
Geerbte Generelle Klasse des BO. */import
application_package
.bo.*;
/*
DBA-Klasse für den Zugriff auf die DB-Tabelle. */
import
application_package
.dba.*;
/**
*
* @author
name[at]company
* @date
20xx-xx-xx
*
* @description
* Server-Side
Klasse für ein Business-Object (BO).
* Variablen
dieses BO und Anwender-bekannte Identifikation sind in der
* (geerbten) Generellen Klasse für das BO
dokumentiert.
*
* @change-log
* when who why
* -----------------------------------------------------------------
*
*/public
class
application_entity
_BOS
extends
application_entity
_BO
{
/*
* VARIABLE dieser Klasse.
* ---------------------
*//* Minimales
Set von Parametern (Benutzer-Name, Arbeitsdatum,
* Identifikation
des Arbeitsplatzes); dieses Set wird vom Client-Side-BO übergeben
. */
private
JSBS_MinimalParameters
structJSBS_MinimalParameters
=
null
;
/*
* Die
folgenden Variablen dienen für die Verwaltung der Verbindung zur
Datenbank.
* --------------------- */
/*
* Referenz
zur DB-Connection die außerhalb dieses Objektes definiert
sind.
* Dieser Wert wird als Parameter in einem
passenden 'Constructor' übergeben. */
private
Connection
structDBCon
=
null
;
/*
* Flag,
ob dieses Objekt von einem BOC (Business Object, Client-Side-Class)
oder
* EJB (Enterprise Java Bean) konstruiert
wurde.
* Wenn das Flag den Wert 'false' hat, dann wurde
dieses Objekt von einen anderen
* BOS (Business Object,
Server-Side-Class) konstruiert.
* Dieses Flag
entscheidet, ob innerhalb dieses Objektes ein 'commit' ausgeführt
wird.
* Ein 'commit' wird nur in jenem Objekt
ausgeführt, das von einem BOC oder EJB konstruiert
* wurde
– nicht in einem Objekt, das von einem anderen BOS konstruiert
wurde. */
private
boolean
bol_ObjectConstructedByBOC_or_EJB
;
/*
* ---------------------
* Die
folgende Variable ist das DBA-Objekt für den Zugriff auf die
DB-Tabelle.
* Dieses DBA-Objekt wird mehrfach gebraucht
und deswegen global in der Klasse definiert. */
private
application_dbtable
_DBA
struct
application_dbtable
_DBA
=
new
application_dbtable
_DBA();
/* --------------------
* CONSTRUCTOR-METHODEN *//* --------------------
* Im 'Constructor' werden Parameter beim Erstellen
eines Objektes dieser Klasse
* übergeben.
* Damit
eine BOS-Klasse (BOS: Business Object, Server-Side) auch innerhalb
eines
* EJB (Enterprise Java Bean) verwendet werden
kann, muss bereits eine Connection
* zur Datenbank als
Parameter an den 'Constructor' übergeben werden.
* Für
ein 'Set' ist es nicht erforderlich, einen 'Constructor' zu
implementieren mit
* dem auch die Werte eines anderen
Objektes übernommen werden können.
*//* ---------------------
*/
/*
* Constructor-Methode mit Minimal-Parametern und
geöffneter DB-Connection als Parameter. */
public
application_entity
_BOS(
JSBS_MinimalParameters
parmMinParm,
Connection
parmDBCon)
{
/*
* Aufruf der Unterstützungs-Methode zur Übernahme
der Parameter-Werte.
*/
constructionWithDBConnection(parmMinParm,
parmDBCon);/*
* Annahme, dass dieses Objekt nicht durch ein BOC oder
EJB konstruiert wurde.
* Überlegung zu der
unlogisch erscheinenden Entscheidung:
* + Wenn dieses
BOS-Objekt innerhalb eines BOC oder EJB konstruiert wird, dann ist
zu
* erwarten, dass für die Klasse des
BOC oder EJB das entsprechende Design-Pattern (Muster)
* verwendet
wird.
* In diesem Muster ist als Vorgabe
der entsprechende Parameter beim Aufruf des
'Constructors'
* enthalten und damit wird
diese 'Constructor'-Methode nicht aufgerufen.
* + Wenn
dieses BOS-Objekt innerhalb eines anderen BOS konstruiert wird, ist
es zeitsparend
* und einfacher
verständlich, diese 'Constructor'-Methode aufzurufen.
* Mit
dem folgenden Kommando wird das entsprechende Flag gesetzt und damit
verhindert,
* dass versehentlich ein
'commit' oder 'rollback' zu früh innerhalb einer Transaktion
* ausgeführt wird.
*/
bol_ObjectConstructedByBOC_or_EJB
=
false
;
}/*
* Constructor-Methode mit Minimal-Parametern,
geöffneter DB-Connection und
* Flag, ob das Objekt
von einem anderen BOS konstruiert wird, als Parameter. */
public
application_entity
_BOS(
JSBS_MinimalParameters
parmMinParm,
Connection
parmDBCon,
boolean
parmObjectConstructedByBOC_or_EJB)
{
/*
* Aufruf der Unterstützungs-Methode zur Übernahme
der Parameter-Werte.
*/
constructionWithDBConnection(parmMinParm,
parmDBCon);/*
* Setzen des Flags aus dem Parameter-Wert.
*/
bol_ObjectConstructedByBOC_or_EJB
=
parmObjectConstructedByBOC_or_EJB;
}/*
* Constructor-Methode mit Minimal-Parametern,
geöffneter DB-Connection und
* einem BO der
gleichen Klasse (aus dem die Werte übernommen werden) als
Parameter. */
public
application_entity
_BOS(
JSBS_MinimalParameters
parmMinParm,
Connection
parmDBCon,
application_entity
_BO
parm
application_entity
_BO)
{
/*
* Aufruf der Unterstützungs-Methode zur Übernahme
der Parameter-Werte.
*/
constructionWithDBConnection(parmMinParm,
parmDBCon);/*
* Aufruf der Unterstützungs-Methode zur Übernahme
der Werte aus einem als Parameter
* übergebenem
BO. Diese Methode ist in der geerbten generellen Klasse
implementiert.
*/
copyFromapplication_entity
_BO(parm
application_entity
_BO);
/*
* Annahme, dass dieses Objekt nicht durch ein BOC oder
EJB konstruiert wurde.
* Überlegung zu der
unlogisch erscheinenden Entscheidung:
* + Wenn dieses
BOS-Objekt innerhalb eines BOC oder EJB konstruiert wird, dann ist
zu
* erwarten, dass für die Klasse des
BOC oder EJB das entsprechende Design-Pattern (Muster)
* verwendet
wird.
* In diesem Muster ist als Vorgabe
der entsprechende Parameter beim Aufruf des
'Constructors'
* enthalten und damit wird
diese 'Constructor'-Methode nicht aufgerufen.
* + Wenn
dieses BOS-Objekt innerhalb eines anderen BOS konstruiert wird, ist
es zeitsparend
* und einfacher
verständlich, diese 'Constructor'-Methode aufzurufen.
* Mit
dem folgenden Kommando wird das entsprechende Flag gesetzt und damit
verhindert,
* dass versehentlich ein
'commit' oder 'rollback' zu früh innerhalb einer Transaktion
* ausgeführt wird.
*/
bol_ObjectConstructedByBOC_or_EJB
=
false
;
}/*
* Constructor-Methode mit Minimal-Parametern,
geöffneter DB-Connection,
* einem BO der gleichen
Klasse (aus dem die Werte übernommen werden) als
Parameter
* und Flag, ob das Objekt von einem anderen
BOS konstruiert wird, als Parameter. */
public
application_entity
_BOS(
JSBS_MinimalParameters
parmMinParm,
Connection
parmDBCon,
application_entity
_BO
parm
application_entity
_BO,
boolean
parmObjectConstructedByBOC_or_EJB)
{
/*
* Aufruf der Unterstützungs-Methode zur Übernahme
der Parameter-Werte.
*/
constructionWithDBConnection(parmMinParm,
parmDBCon);/*
* Aufruf der Unterstützungs-Methode zur Übernahme
der Werte aus einem als Parameter
* übergebenem
BO. Diese Methode ist in der geerbten generellen Klasse
implementiert.
*/
copyFromapplication_entity
_BO(parm
application_entity
_BO);
/*
* Setzen des Flags aus dem Parameter-Wert.
*/
bol_ObjectConstructedByBOC_or_EJB
=
parmObjectConstructedByBOC_or_EJB;
}/* ---------------------
* METHODEN zur UNTERSTÜTZUNG der Übernahme
der Parameter der CONSTRUCTOR-Methoden.
* In diesen Methoden
werden die Parameter, die in unterschiedlichen
Constructor-Methoden
* übernommen wurden auf die
Variablen dieses Objekts übertragen.
* ---------------------
*//*
* METHODE zum Übernehmen einer bereits geöffneten
DB-Connection (Verbindung zur Datenbank). */
private
void
constructionWithDBConnection(
JSBS_MinimalParameters
parmMinParm,
Connection
parmDBConnection)
{
/*
* Kopieren der Werte aus dem Minimalen Set der
Parameter in die Variable dieses Objekts.
*/
structJSBS_MinimalParameters
=
new
JSBS_MinimalParameters(parmMinParm);
/*
* Übertragen der Referenz auf die DB-Connection
(Verbindung zur Datenbank)
* in die entsprechende
Variable dieses Objekts. */
structDBCon
=
parmDBConnection;
}/* ---------------------
* ELEMENTARE METHODEN für gesteuerte 'commit' und
'rollback' und 'insert' und 'update' der
* haupt-zugeordneten
DB-Tabelle.
* --------------------- *//*
* METHODE
zum Ausführen eines 'commit' auf eine Datenbank.
* Diese
Methode wird in den Methoden zum Ausführen von Änderungen
und Abfragen auf der
* Datenbank zum Abschluss
aufgerufen und damit werden die Änderungen auf der Datenbank
gültig.
* Bei Abfragen (ohne Änderung von
Werten) wäre ein 'commit' nicht notwendig – durch Fehler
beim
* Code für das Erstellen der 'Connection'
zur Datenbank kann es aber passieren, dass die 'Connection'
* nicht
mit 'autocommit' geöffnet wird und dann tritt bei verschiedenen
DB-Systemen ein Fehler auf
* wenn vor dem Beenden der
'Connection' kein 'commit' oder 'rollback' ausgeführt
wurde.
* Der Code in dieser Methode ist ein
'Sicherheitsnetz' um den Zugriff auf die DB auf jeden Fall
* korrekt
zu beenden. */
private
void
commitDBConnection()
{
/*
* Wenn
die DB-Connection nicht in dem Objekt, in dem dieses Objekt
'konstruiert' wurde, geöffnet wurde,
* dann wird
diese Methode sofort abgebrochen weil dann das 'commit' in einer
'darüber liegenden'
* Methode ausgeführt
wird. */
if
(!
bol_ObjectConstructedByBOC_or_EJB)
return
;
/* 'commit'
über die try/catch-Logik ausführen damit ein eventueller
Fehler beim 'commit'
* abgefangen werden kann.
*/
try
{
/* Ermitteln
ob die Verbindung zur Datenbank im 'AutoCommit' Modus geöffnet
wurde – dann ist kein
* explizites 'commit'
notwendig. */
if
(!
structDBCon
.getAutoCommit())
{
structDBCon
.commit();
}
}
catch
(SQLException SQLExc)
{
/* Fehler
beim Ausführen des 'commit'; Fehler an die aufrufende Methode
zurückliefern. */
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
SQLExc.getMessage();
/* Um
auf der sicheren Seite zu sein wird gleich noch ein 'rollback'
ausgeführt.
*/
rollbackDBConnection();
}
}/*
* METHODE
zum Ausführen eines 'rollback' auf eine Datenbank.
* Diese
Methode wird aufgerufen wenn in den Methoden zum Ausführen von
Änderungen auf der
* Datenbank ein Fehler
aufgetreten ist und die bisher durchgeführten Änderungen
rückgängig
* gemacht werden müssen.
*/
private
void
rollbackDBConnection()
{
/*
* Wenn
die DB-Connection nicht in dem Objekt, in dem dieses Objekt
'konstruiert' wurde, geöffnet wurde,
* dann wird
diese Methode sofort abgebrochen weil dann das 'rollback' in einer
'darüber liegenden'
* Methode ausgeführt
wird. */
if
(!
bol_ObjectConstructedByBOC_or_EJB)
return
;
/* 'rollback'
über die try/catch-Logik ausführen damit ein eventueller
Fehler abgefangen werden kann. */
try
{
/* Ermitteln
ob die Verbindung zur Datenbank im 'AutoCommit' Modus geöffnet
wurde – dann ist ein
* 'rollback' sinnlos weil
die 'commit'-Schritte durch das Datenbanksystem bestimmt werden.
*/
if
(!
structDBCon
.getAutoCommit())
{
structDBCon
.rollback();
}
}
catch
(SQLException SQLExc)
{
/* Fehler
beim Ausführen des 'commit'; Fehler an die aufrufende Methode
zurückliefern. */
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
SQLExc.getMessage();
}
}/*
* METHODE
zum Übertragen der Attribute auf das haupt-zugeordnete
DBA-Objekt. */
private
void
setDBAAttributes(
application_dbtable
_DBA
parm
application_dbtable
_DBA)
{
/*
* Aufruf
der Methode der geerbten Klasse (Superklasse) um die 'Common
Attributes'
* zu kopieren.
*/
super
.setCommonDBAAttributes(parm
application_dbtable
_DBA);
/*
* Übertragen
der geschäfts-spezifischen Werte dieses BO.
*/
parmapplication_dbtable
_DBA.
VariableName
=
this
.
BO_VariableName
;
}/*
* METHODEN
zum Einfügen eines Datensatzes in die DB-Tabelle.
* Mit
den verschiedenen Parametern wird gesteuert, welchen
* Gültigkeitszeitraum der eingefügte
Datensatz hat. *//*
* METHODE
für ein einfaches Einfügen eines Datensatzes in die
DB-Tabelle.
* Mit dem Parameter wird gesteuert, ob die
Attribute 'ObjectID', 'CreatedAt'
* und 'CreatedBy'
mit Werten versorgt werden müssen.
* Der
Gültigkeitszeitraum beginnt mit dem aktuellen Datum und ist 'bis
auf Weiteres'. */
private
void
internalInsert(
boolean
parmFirstInsert)
{
/*
*
Methode 'internalInsert' mit Parameter für das
Gültigkeits-Anfangs-Datum
* und das
Gültigkeits-Ende-Datum aufrufen.
*/
internalInsert(parmFirstInsert,
JSBS_BO_Services.getNewValidFrom(
structJSBS_MinimalParameters
),
JSBS_BO_Services.getGoodTillCancelled_SQLDate());
}/*
* METHODE
zum Einfügen eines Datensatzes in die DB-Tabelle.
* Dabei
wird der Gültigkeitszeitraum in den Parametern übergeben.
* Mit
diesem Service kann die aufrufende Methode einfacher gehalten werden.
*/
private
void
internalInsert(
boolean
parmFirstInsert,
java.sql.Date
parmValidFrom,
java.sql.Date
parmValidTill)
{
/*
* Gültigkeit
des Datensatzes aus den Parametern übernehmen.
*/
ValidFrom
= parmValidFrom;
ValidTill
= parmValidTill;
/*
* Anwender
dessen Eingabe das Einfügen des Datensatzes ausgelöst hat
im zuständigen
* Attribut speichern und Systemzeit
(des Computers) übernehmen. */
ChangedBy
=
structJSBS_MinimalParameters
.
strUserName
;
ChangedAt
=
new
Timestamp(
new
Date().getTime());
/*
* Holen
eines Surrogates (künstlicher Schlüssel) über die
entsprechende Methode
* und Prüfen, ob das
Surrogat bereits als Wert für einen 'DataSetID' verwendet
wurde.
* Dabei werden maximal 9 Versuche durchgeführt
einen 'ungebrauchten' Wert zu finden. */
int
intTrialCounter
= 9;
do
{
/* Methode,
die eine weit gestreute Zufallszahl liefert, aufrufen.
*/
DataSetID
=
JSBS_BO_Services.generateSurrogate();
/* Datenbankzugriff
zum Prüfen ob dieses Surrogate bereits als Schlüssel
benutzt wird. */
boolean
locbolDataSetExists
=
struct
application_dbtable
_DBA
.selectByDataSetID(
structDBCon
,
this
.
DataSetID
);
/* Prüfen
ob der seltene Fall eingetreten ist, dass das Surrogat bereits
verwendet wird. */
if
(locbolDataSetExists)
{
/* Reduzieren
des Zählers der noch durchzuführenden Versuche
und
* wieder am Anfang der Schleife beginnen.
*/
intTrialCounter--;
continue
;
}
else
{
/* Vor
dem weiterarbeiten prüfen ob nicht ein Fehler beim DB-Zugriff
aufgetreten ist.
* Ein Fehler wird durch eine nicht
leere Error-Message signalisiert. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
structapplication_dbtable_DBA
.
ErrorMsg
;
/* Verarbeitung
abbrechen. */
return
;
}/* DBA-Objekt
mit generiertem Surrogat existiert noch nicht. Verarbeitung
fortsetzen. */
if
(parmFirstInsert)
{
/* Erstes
Data-Set eines neuen Daten-Objekts wird eingefügt.
* Entsprechende
Common Attributes versorgen. */
ObjectID
=
DataSetID
;
CreatedAt
=
ChangedAt
;
CreatedBy
=
ChangedBy
;
}/* Methode
zum Einfügen wenn bereits alle Attribute versorgt sind,
aufrufen. */
internalInsert();/* INSERT
abgeschlossen; Methode beenden.
*/
return
;
}
}
while
(intTrialCounter
> 0);
/*
* Alle
9 generierten Surrogats-Werte sind bereits als Schlüssel
verwendet.
* Das weist auf eine volle DB-Tabelle hin –
das in die Fehlermeldung schreiben. */
StatusCode
=
CONST_DB_UNKNOWN_ERROR
;
StatusMsg
=
"No
surrogate found after 9 trials; database-table seems to be
full."
;
}/*
* METHODE
zum Einfügen eines Datensatzes in die DB-Tabelle wenn bereits
alle Attribute
* mit Werten versorgt sind.
*/
private
void
internalInsert()
{
/* Übertragen
der Werte der Variablen dieses BO auf die Variablen des DBA-Objektes.
*/
setDBAAttributes(struct
application_dbtable
_DBA
);
/* Aufrufen
der Methode die das SQL-INSERT in die DB-Tabelle ausführt.
*/
struct
application_dbtable
_DBA
.insert(
structDBCon
);
/*
* Prüfen
ob bei der DB-Operation ein Fehler aufgetreten ist. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
}/* INSERT
abgeschlossen; Methode beenden. */
return
;
}/*
* METHODE
zum Update eines bestehenden Datensatzes.
* Die Verarbeitung
ist sehr einfach weil die Geschäftslogik in der nach
* 'außen'
sichtbaren Methode ('store') vorhanden ist. */
private
void
internalUpdate()
{
/*
* Übertragen
der Werte der Variablen dieses BO auf die Variablen des DBA-Objektes.
*/
setDBAAttributes(struct
application_dbtable
_DBA
);
/* Aufrufen
der Methode die das SQL-UPDATE in der DB-Tabelle ausführt.
*/
struct
application_dbtable
_DBA
.update(
structDBCon
);
/*
* Prüfen
ob bei der DB-Operation ein Fehler aufgetreten ist. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
}/* UPDATE
abgeschlossen; Methode beendet. */
}/* ---------------------
* METHODE zum Speichern eines BO wobei die Werte in
den Attributen so wie sie sind
* auf die
Datenbank-Tabelle geschrieben werden.
* Ist der Wert im
Parameter 'parmDataSetIDToSelect' nicht '0' dann wird der
Datensatz
* mit dem im Parameter übergebenen
Primärschlüssel verändert und als neuer
Primärschlüssel
* wird der Wert von
'DataSetID' in diesem BO verwendet.
* Diese Methode ist
dafür vorgesehen bei einer 'MobileClient' Version die Daten
zwischen
* einem mobilen Client und dem Server
abgleichen zu können. */
public
synchronized void
synchronizedStore(
double
parmDataSetIDToSelect)
{
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Prüfen, ob der Primärschlüssel
(DataSetID) geändert werden soll.
* In diesem Fall
eine eigene Methode aufrufen damit diese Methode überschaubar
bleibt. */
if
((
parmDataSetIDToSelect
!= 0
)
&&
(
this
.
DataSetID
!=
parmDataSetIDToSelect))
{
synchronizedStoreWithPrimaryKeyChange(parmDataSetIDToSelect);
return
;
}/*
* Ein eigenes BOS erstellen und damit Prüfen, ob
bereits ein Datensatz mit gleichem
* Primärschlüssel
existiert.
* Ein eigenes BOS ist notwendig weil sonst
beim Lesen die Werte in diesem BOS
* überschrieben
würden. */
application_entity
_BOS
existing
application_entity
_BOS
=
new
application_entity
_BOS(
structJSBS_MinimalParameters
,
structDBCon
,
false
);
existing
application_entity
_BOS.selectByDataSetID(
this
.
DataSetID
);
/*
* Abhängig davon, ob bereits ein Datensatz mit
gleichem Primärschlüssel existiert,
* diesen
Ändern oder einen neuen Datensatz einfügen. */
switch
(existing
application_entity
_BOS.
StatusCode
)
{
case
JSBS_BO.
CONST_NOT_FOUND
:
/* Datensatz
mit gleichem Primärschlüssel existiert noch nicht; Methode
zum Einfügen aufrufen.
*/
internalInsert();
break
;
case
JSBS_BO.
CONST_OK
:
/* Datensatz
mit gleichem Primärschlüssel existiert; Methode zum Ändern
aufrufen.
*/
internalUpdate();
break
;
default
:
/* Unerwarteter
Fehler beim Datenbank-Zugriff; kann nicht durch das
Anwendungsprogramm behoben werden.
* Status-Code und
-Meldung auf dieses BO übertragen. */
this
.
StatusCode
=
existing
application_entity
_BOS.
StatusCode
;
this
.
StatusMsg
=
existing
application_entity
_BOS.
StatusMsg
;
return
;
}
}/* ---------------------
* METHODE zum Speichern eines BO wobei die Werte in
den Attributen und dabei auch
* der Primärschlüssel
(DataSetID) geändert wird.
* Diese Methode ist
dafür vorgesehen bei einer 'MobileClient' Version die Daten
zwischen
* einem mobilen Client und dem Server
abgleichen zu können.
* Dieser
spezielle Code wurde deswegen in eine eigene Methode ausgegliedert
weil auch
* geprüft
werden muss, ob nicht bereits ein Datensatz mit dem neuen
Primärschlüssel
* existiert
und diesem Datensatz ein neuer Primärschlüssel zugeordnet
werden muss.
*
Dieser sehr seltene Fall kann nur dann eintreten wenn gleichzeitig
auf dem mobilen Client
* und
dem Server
der
gleiche Primärschlüssel für verschiedene Objekte
vergeben wurde. */
private
synchronized void
synchronizedStoreWithPrimaryKeyChange(
double
parmDataSetIDToSelect)
{
/*
* Ein eigenes BOS erstellen zum Prüfen (in der
folgenden for-Schleife). */
application_entity
_BOS
existing
application_entity
_BOS
=
new
application_entity
_BOS(
structJSBS_MinimalParameters
,
structDBCon
,
false
);
/*
* 'Ewige' for Schleife zum Prüfen ob der neue
Primärschlüssel (this.DataSetID) noch nicht
*
bei einem Datensatz existiert bzw. Ändern des Primärschlüssels
bei dem Datensatz, der
*
diesen Primärschlüssel verwendet. */
for
(;;)
{
/*
* Prüfen, ob bereits ein Datensatz mit dem neuen
Primärschlüssel (DataSetID) existiert.
*/
existing
application_entity
_BOS.selectByDataSetID(
this
.
DataSetID
);
/*
* Abhängig davon, ob bereits ein Datensatz mit
gleichem Primärschlüssel existiert,
* bei diesem
den Primärschlüssel andern oder die Daten aus diesem BO in
den als Datensatz einfügen. */
switch
(existing
application_entity
_BOS.
StatusCode
)
{
case
JSBS_BO.
CONST_NOT_FOUND
:
/*
* Datensatz
mit neuem Primärschlüssel existiert noch nicht.
*
Das Ändern des bestehenden Datensatzes wird direkt über das
DBA ausgeführt weil dort
* die passende Methode
vorhanden ist.
* Zuerst Übertragen der Werte der
Variablen dieses BO auf die Variablen des DBA-Objektes.
*/
setDBAAttributes(
struct
application_dbtable
_DBA
);
/* Aufrufen
der Methode die das SQL-UPDATE in der DB-Tabelle ausführt.
*/
struct
application_dbtable
_DBA
.update(
structDBCon
,
parmDataSetIDToSelect);
/*
* Prüfen
ob bei der DB-Operation ein Fehler aufgetreten ist. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
}
/* UPDATE
abgeschlossen; Methode beenden. */
return
;
case
JSBS_BO.
CONST_OK
:
/*
* Seltener Fall, dass ein Datensatz mit neuem
Primärschlüssel bereits existiert;
* eigene
Methode zum Ändern aufrufen.
*/
existing
application_entity
_BOS.changePrimaryKey();
/*
Prüfen, ob ein Fehler aufgetreten ist. */
if
(existing
application_entity
_BOS.
StatusCode
!=
JSBS_BO.
CONST_OK
)
{
/* Unerwarteter
Fehler beim Datenbank-Zugriff; kann nicht durch das
Anwendungsprogramm behoben werden.
* Status-Code und
-Meldung auf dieses BO übertragen und Methode beenden.
*/
this
.
StatusCode
=
existing
application_entity
_BOS.
StatusCode
;
this
.
StatusMsg
=
existing
application_entity
_BOS.
StatusMsg
;
return
;
}
break
;
default
:
/* Unerwarteter
Fehler beim Datenbank-Zugriff; kann nicht durch das
Anwendungsprogramm behoben werden.
* Status-Code und
-Meldung auf dieses BO übertragen. */
this
.
StatusCode
=
existing
application_entity
_BOS.
StatusCode
;
this
.
StatusMsg
=
existing
application_entity
_BOS.
StatusMsg
;
return
;
}
}
}/* ---------------------
* METHODE zum Ändern des Primärschlüssels
(DataSetID) bei einem bestehenden Datensatz.
* Dieser sehr
seltene Fall kann nur dann eintreten wenn gleichzeitig auf dem
mobilen Client
* und
dem Server
der
gleiche Primärschlüssel für verschiedene Objekte
vergeben wurde
* und auf der Datenbank des mobilen
Clients der Primärschlüssel geändert werden muss.
*/
protected
synchronized void
changePrimaryKey()
{
/*
* Aufheben des bestehenden Primärschlüssels um
später den zu ändernden Datensatz wieder
* von der
Datenbank lesen zu können. */
double
dblOriginalDataSetID
= this.
DataSetID
;
/*
* Holen
eines Surrogates (künstlicher Schlüssel) über die
entsprechende Methode
* und Prüfen, ob das
Surrogat bereits als Wert für einen 'DataSetID' verwendet
wurde.
* Dabei werden maximal 9 Versuche durchgeführt
einen 'ungebrauchten' Wert zu finden. */
int
intTrialCounter
= 9;
do
{
/* Methode,
die eine weit gestreute Zufallszahl liefert, aufrufen.
*/
DataSetID
=
JSBS_BO_Services.generateSurrogate();
/* Datenbankzugriff
zum Prüfen ob dieses Surrogate bereits als Schlüssel
benutzt wird. */
boolean
locbolDataSetExists
=
struct
application_dbtable
_DBA
.selectByDataSetID(
structDBCon
,
this
.
DataSetID
);
/* Prüfen
ob der seltene Fall eingetreten ist, dass das Surrogat bereits
verwendet wird. */
if
(locbolDataSetExists)
{
/* Reduzieren
des Zählers der noch durchzuführenden Versuche
und
* wieder am Anfang der Schleife beginnen.
*/
intTrialCounter--;
continue
;
}
else
{
/* Vor
dem weiterarbeiten prüfen ob nicht ein Fehler beim DB-Zugriff
aufgetreten ist.
* Ein Fehler wird durch eine nicht
leere Error-Message signalisiert. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Verarbeitung
abbrechen. */
return
;
}/* DBA-Objekt
mit generiertem Surrogat existiert noch nicht.
* Für
dieses BO ein UPDATE auf der Datenbank ausführen.
*/
setDBAAttributes(
struct
application_dbtable
_DBA
);
/* Aufrufen
der Methode die das SQL-UPDATE in der DB-Tabelle ausführt.
*/
struct
application_dbtable
_DBA
.update(
structDBCon
,
dblOriginalDataSetID);
/*
* Prüfen
ob bei der DB-Operation ein Fehler aufgetreten ist. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
}
/* UPDATE
abgeschlossen; Methode beenden.
*/
return
;
}
}
while
(intTrialCounter
> 0);
}/*
********************
* METHODEN FÜR
GESCHÄFTSBEZOGENE VERARBEITUNG.
* Diese Methoden
werden in der Client-Side-Klasse für das Business Object
(BO)
* aufgerufen wenn Daten gespeichert werden
müssen.
*
* Die Methode 'store'
unterscheidet ob ein Geschäftsobjekt (BO / Business-Object)
* erstmalig gespeichert werden muß oder die
Daten eines bestehenden BO geändert wurden.
*
* Die
Methoden 'select....' führen eine Abfrage durch.
* In
dieser Klasse sind aber nur 'select...'-Methoden implementiert, die
per Definition
* maximal einen Datensatz
auswählen.
* Methoden die mehr als einen Datensatz
finden könnten, werden in der
Klasse
* application_entity
_Set_BOS_Set
implementiert.
* ---------------------
*//*
* METHODE
zum Speichern der Werte in den Variablen dieses BO.
* Oder
technisch: Die Daten werden persistent gemacht.
*
* Die
Methode unterscheidet, ob ein neues BO eingefügt werden soll
oder ob
* geschäfts-relevante Werte eines
bestehenden BO verändert wurden.
*
* Ein
BO ist durch eine eindeutige Anwender-Identifikation
definiert.
* Sehen Sie bitte bei der Methode
'selectByUserKnownKey(.....)' nach, welche
* Variable
die Anwender-Identifikation bilden.
*
* Ein
neues BO wird dann eingefügt, wenn das 'Common Attribute'
ObjectID den
* Wert 0 enthält. */
public
synchronized void
store()
{
/*
Methode aufrufen in der eventuell die Daten des BO noch einmal auf
Konsistenz geprüft
* werden. */
if
(!
isConsistentData())
return
;
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Entscheiden ob das BO neu erstellt wurde (ObjectID
gleich 0) oder
* eine Änderung eines Wertes einer
Geschäfts-relevanten-Variable erfolgt ist. */
if
(
ObjectID
==
0) {
/*
* Speichern eines neuen Business-Object
angefordert.
* Prüfen, dass noch kein BO mit der
gleichen Anwender-bekannten Identifikation existiert.
*/
boolean
locbolDataSetExists
=
struct
application_dbtable
_DBA
.selectByUserKnownKey(
structDBCon
,
structJSBS_MinimalParameters
,
this
.
KeyVariable_1
,
this
.
KeyVariable_2
);
if
(locbolDataSetExists)
{
/* BO
mit der gleichen Anwender-bekannten Identifikation existiert bereits
auf der DB-Tabelle.
* Fehler an aufrufende Methode
signalisieren, Rollback einleiten und Methode beenden.
*/
StatusCode
=
CONST_DUPLICATE_KEY
;
StatusMsg
=
""
;
rollbackDBConnection();
return
;
}
else
{
/* Kein
entsprechender Datensatz gefunden; könnte aber auch ein Fehler
beim DB-Zugriff sein. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Rollback
einleiten und Methode beenden.
*/
rollbackDBConnection();
return
;
}
}/*
* Wenn
die Verarbeitung bis hierher gelaufen ist, existiert kein BO mit
der
* gleichen Anwender-bekannten Identifikation und
die DB-Abfrage danach war fehlerfrei.
*
* Neuen
Datensatz für dieses BO in die DB-Tabelle einfügen.
* Der
Prameter signalisiert, dass es sich um den ersten Datensatz für
ein neues BO handelt. */
internalInsert(true
);
/* Prüfen
ob bei der aufgerufenen Methode ein Fehler aufgetreten ist.
*/
if
(
StatusCode
!=
CONST_OK
)
{
/* Status
für dieses BO wurde in der Methode 'internalInsert(...)' in die
passenden Variablen
* übertragen. Rollback
einleiten und Methode beenden.
*/
rollbackDBConnection();
return
;
}
}
else
{
/*
* Änderung eines Wertes einer
Geschäfts-relevanten-Variable erfolgt.
* Die
Gültigkeit des aktuell gültigen Datensatzes wird auf den
Tag vor
* dem Arbeitsdatum (ein Parameter aus dem
minimalen Set der Parameter) gesetzt.
* Das ist das
Zeichen, dass der Datensatz nicht länger gültig
ist.
* Dann wird ein neuer Datensatz mit dem gleichen
ObjectID eingefügt,
* dessen Gültigkeitsbeginn
('ValidFrom') das aktuelle Arbeitsdatum ist. */
/*
* Zuerst
wird der aktuell gültige Datensatz gelesen um zu prüfen, ob
ein anderer
* Anwender eine Änderung vorgenommen
hat.
* Die Änderung könnte in der Zeit
passiert sein, als der jetzt zu ändernde Datensatz
* gelesen
wurde (um die Daten anzuzeigen) und jetzt, wo die geänderten
Daten
* gespeichert werden sollen.
*
* Zum
Lesen des Vergleichs-BOS wird ein neues BOS 'konstruiert' und dabei
die bestehende
* DB-Connection als Parameter übergeben.
*/
application_entity
_BOS
existing
application_entity
_BOS
=
new
application_entity
_BOS(
structJSBS_MinimalParameters
,
structDBCon
,
false
);
/*
* Datensatz
mit dem DatasetID lesen; das bringt den Datensatz der vor einiger
Zeit
* gelesen wurde.
*/
existingapplication_entity
_BOS.selectByDataSetID(
this
.
DataSetID
);
/* Mit
der aufgerufenen Methode muß ein Datensatz gefunden
werden.
* Wenn das nicht der Fall ist, dann eine
Fehlerbehandlung durchführen. */
if
(existing
application_entity
_BOS.
StatusCode
!=
CONST_OK
)
{
/* Datensatz
nicht gefunden oder ein Fehler beim DB-Zugriff ist
aufgetreten.
* Status-Code in dieses Objekt übernehmen
und Fehlermeldung anpassen. */
this
.
StatusCode
=
existing
application_entity
_BOS.
StatusCode
;
this
.
StatusMsg
=
"Unexpected
Error during re-read:"
+
existingapplication_entity
_BOS.
StatusMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}/* Datensatz
gefunden; so sollte es sein. */
/* Zuerst
prüfen ob die Gültigkeit des Datensatzes in der
Zwischenzeit beendet wurde.
* Das weist auf eine
Veränderung des BO hin. */
if
(
this
.differentValidTill(
existingapplication_entity
_BOS.
ValidTill
)){
/* Anderer
Benutzer hat das BO inzwischen verändert.
*/
this
.
StatusCode
=
CONST_CHANGED_INBETWEEN
;
this
.
StatusMsg
=
""
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}/* Noch
prüfen ob überhaupt ein Wert einer geschäfts-relevanten
Variable verändert wurde.
* Wenn keine Veränderung
erfolgt ist wird auch kein neuer Datensatz eingefügt.
*/
if
(!
this
.isDifferent(existing
application_entity
_BOS)){
/* Keine
Änderung eines Wertes einer geschäftsrelevanten Variable.
*/
this
.
StatusCode
=
CONST_NOTHING_TO_UPDATE
;
this
.
StatusMsg
=
""
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
/*
* Gültigkeit
des bestehenden Datensatzes als 'beendet' markieren.
* Das
wird durch ein Datum vor dem aktuellen Arbeitsdatum indiziert.
*/
existingapplication_entity
_BOS.
ValidTill
=
JSBS_BO_Services.getNewValidTill(structJSBS_MinimalParameters
);
/* Änderung
des bestehenden Datensatzes auf der DB-Tabelle durchführen.
*/
existingapplication_entity
_BOS.internalUpdate
(
);
/* Prüfen
ob das Update fehlerfrei durchgeführt wurde.
* Wenn
das nicht der Fall ist, dann eine Fehlerbehandlung durchführen.
*/
if
(existing
application_entity
_BOS.
StatusCode
!=
CONST_OK
)
{
/* Datensatz
nicht gefunden oder ein Fehler beim DB-Zugriff ist
aufgetreten.
* Status-Code in dieses Objekt übernehmen
und Fehlermeldung anpassen. */
this
.
StatusCode
=
existing
application_entity
_BOS.
StatusCode
;
this
.
StatusMsg
=
"Unexpected
Error during update of existing record: "
+
existingapplication_entity
_BOS.
StatusMsg
;
/* Rollback
ausführen und wenn notwendig die DB-Connection
schließen.
* Anschließend Methode beenden.
*/
rollbackDBConnection();
return
;
}
/*
* Als
letzte Datenbank-Operation einen neuen Datensatz mit den aktuellen
Werten
* in die DB-Tabelle einfügen.
*
Der Parameter ('false') teilt der aufgerufenen Methode mit, dass
der
* Datensatz eine Änderung eines bestehenden BO
ist. */
internalInsert(false
);
/* Prüfen
ob das Insert fehlerfrei durchgeführt wurde.
* Wenn
das nicht der Fall ist, dann eine Fehlerbehandlung durchführen.
*/
if
(
this
.
StatusCode
!=
CONST_OK
)
{
/* Status
für dieses BO wurde in der Methode 'internalInsert(...)' in die
passenden Variablen
* übertragen. Rollback
einleiten und Methode beenden.
*/
rollbackDBConnection();
return
;
}/* Alle
DB-Operationen fehlerfrei; 'commit' ausführen.
*/
commitDBConnection();
}
}/*
* METHODE
zum Selektieren eines Datensatzes mit dem Primär-Schlüssel
der DB-Tabelle.
* Es kann nur ein Datensatz gefunden
werden – dieser ist Teil eines Business-Objektes (BO).
*/
public
synchronized
void
selectByDataSetID(
double
parmDataSetID)
{
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
struct
application_dbtable
_DBA
.selectByDataSetID(
structDBCon
,
parmDataSetID
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
* Attributs-Werte
auf die Varaiblen dieses BO übertragen.
*/
getDBAAttributes(struct
application_dbtable
_DBA
);
/* Commit
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
commitDBConnection();
return
;
}
else
{
/* Kein
entsprechender Datensatz gefunden; könnte aber auch ein Fehler
beim DB-Zugriff sein. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
<= 0) {
/* DBA-Objekt
meldet keinen Fehler; d.h. ein passender Datensatz wurde nicht
gefunden.
* Status-Code setzen und Fehler-Meldung leer
lassen. */
StatusCode
=
CONST_NOT_FOUND
;
StatusMsg
=
""
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
else
{
/* DBA-Objekt
meldet einen Fehler;
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
}
}
/*
----------------------
* METHODE zum Selektieren des
aktuell gültigen Datensatzes mit der
* intern
verwendeten Objekt-Identifikation.
* 'Aktuell gültig'
bedeutet, dass die Gültigkeit des Datensatzes mit dem
* im
Minimalen Set von Parametern übergebenen Arbeitsdatum
übereinstimmt.
* Es kann nur ein Datensatz
gefunden werden – dieser ist Teil eines Business-Objektes (BO).
*/
public
synchronized
void
selectByObjectID(
double
parmObjectID)
{
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
struct
application_dbtable
_DBA
.selectByObjectID(
structDBCon
,
structJSBS_MinimalParameters
,
parmObjectID))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
* Attributs-Werte
auf die Variablen dieses BO übertragen.
*/
getDBAAttributes(struct
application_dbtable
_DBA
);
/* Commit
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
commitDBConnection();
return
;
}
else
{
/* Kein
entsprechender Datensatz gefunden; könnte aber auch ein Fehler
beim DB-Zugriff sein. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
<= 0) {
/* DBA-Objekt
meldet keinen Fehler; d.h. ein passender Datensatz wurde nicht
gefunden.
* Status-Code setzen und Fehler-Meldung leer
lassen. */
StatusCode
=
CONST_NOT_FOUND
;
StatusMsg
=
""
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
else
{
/* DBA-Objekt
meldet einen Fehler;
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
}
}
/*
----------------------
* METHODE zum Selektieren des
aktuell gültigen Datensatzes mit der
* Anwender-bekannten
Identifikation.
* 'Aktuell gültig' bedeutet, dass
die Gültigkeit des Datensatzes mit dem
* im
Minimalen Set von Parametern übergebenen Arbeitsdatum
übereinstimmt.
* Es kann nur ein Datensatz
gefunden werden – dieser ist Teil eines Business-Objektes (BO).
*/
public
synchronized
void
selectByUserKnownKey(
String
parm
KeyVariable_1
,
String
parm
KeyVariable_2
)
{
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
struct
application_dbtable
_DBA
.selectByUserKnownKey(
structDBCon
,
structJSBS_MinimalParameters
,
parm
KeyVariable_1
,
parm
KeyVariable_2
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
* Attributs-Werte
auf die Variablen dieses BO übertragen.
*/
getDBAAttributes(struct
application_dbtable
_DBA
);
/* Commit
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
commitDBConnection();
return
;
}
else
{
/* Kein
entsprechender Datensatz gefunden; könnte aber auch ein Fehler
beim DB-Zugriff sein. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
<= 0) {
/* DBA-Objekt
meldet keinen Fehler; d.h. ein passender Datensatz wurde nicht
gefunden.
* Status-Code setzen und Fehler-Meldung leer
lassen. */
StatusCode
=
CONST_NOT_FOUND
;
StatusMsg
=
""
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
else
{
/* DBA-Objekt
meldet einen Fehler;
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
}
}
/*
----------------------
* METHODE zum Selektieren des
Datensatzes mit jener Anwender-bekannten Identifikation,
* die
in der Sortier-Reihenfolge nach den Werten, die als Parameter
übergeben werden,
* auftreten.
* Dabei
kann nur ein Datensatz gefunden werden. */
public
synchronized
void
selectNext(
String
parm
KeyVariable_1
,
String
parm
KeyVariable_2
,
String
parm
KeyVariable_3
)
{
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
struct
application_dbtable
_DBA
.selectNext(
structDBCon
,
structJSBS_MinimalParameters
,
parmKeyVariable_1
,
parm
KeyVariable_2
,
parm
KeyVariable_3
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
* Attributs-Werte
auf die Variablen dieses BO übertragen.
*/
getDBAAttributes(struct
application_dbtable
_DBA
);
/* Commit
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
commitDBConnection();
return
;
}
else
{
/* Kein
entsprechender Datensatz gefunden; könnte aber auch ein Fehler
beim DB-Zugriff sein. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
<= 0) {
/* DBA-Objekt
meldet keinen Fehler; d.h. ein passender Datensatz wurde nicht
gefunden.
* Status-Code setzen und Fehler-Meldung leer
lassen. */
StatusCode
=
CONST_NOT_FOUND
;
StatusMsg
=
""
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
else
{
/* DBA-Objekt
meldet einen Fehler;
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
}
}
/*
---------------------
* METHODE zum Selektieren des
Datensatzes mit jener Anwender-bekannten Identifikation,
* die
in der Sortier-Reihenfolge vor den Werten, die als Parameter
übergeben werden,
* auftreten.
* Dabei
kann nur ein Datensatz gefunden werden. */
public
synchronized
void
selectPrevious(
String
parm
KeyVariable_1
,
String
parm
KeyVariable_2
,
String
parm
KeyVariable_3
)
{
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
struct
application_dbtable
_DBA
.selectPrevious(
structDBCon
,
structJSBS_MinimalParameters
,
parmKeyVariable_1
,
parm
KeyVariable_2
,
parm
KeyVariable_3
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
* Attributs-Werte
auf die Variablen dieses BO übertragen.
*/
getDBAAttributes(struct
application_dbtable
_DBA
);
/* Commit
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
commitDBConnection();
return
;
}
else
{
/* Kein
entsprechender Datensatz gefunden; könnte aber auch ein Fehler
beim DB-Zugriff sein. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
<= 0) {
/* DBA-Objekt
meldet keinen Fehler; d.h. ein passender Datensatz wurde nicht
gefunden.
* Status-Code setzen und Fehler-Meldung leer
lassen. */
StatusCode
=
CONST_NOT_FOUND
;
StatusMsg
=
""
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
else
{
/* DBA-Objekt
meldet einen Fehler;
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
}
}
/*
-----------------------------
* METHODE zum
'Deaktivieren' dieses BO.
* 'Deaktivieren' bedeutet, dass
die Gültigkeit des aktuellen Datensatzes und eventuell
*
in Zukunft gültiger Datensätze beendet wird.
*
Dazu wird in den Datensätzen, deren 'ValidTill' (Gültig Bis
Datum) gleich
oder
größer
* ist als das aktuelle Datum (das beim
'Konstruieren' dieses Objektes als Teil der
* Struktur
'JSBS_MinimalParameters' übergeben wurde), ValidTill auf den Tag
vor dem
* aktuellen Tag gesetzt.
* Zur
Dokumentation wer (welcher Anwender) zu welcher Systemzeit das
Deaktivieren
* ausgeführt hat, wird ein neuer Datensatz
eingefügt der mit dem aktuellen Datum beginnt
* und am
Tag vor dem aktuellen Datum endet. */
public
synchronized
void
deactivate()
{
/* Variable
für den Status auf OK (fehlerfrei) setzen.
*/
this
.
StatusCode
=
CONST_OK
;
this
.
StatusMsg
=
""
;
/*
* Prüfen, ob das BO überhaupt deaktiviert werden
darf.
* Ein eventueller (Fehler-)Status-Code wird in der
Methode 'isReferenced' gesetzt. */
if
(isReferenced())
{
/*
Das BO darf nicht deaktiviert werden weil es noch von einem anderen
BO referenziert wird.
* Status-Code (warum das BO nicht
deaktiviert werden darf) und Status-Message
*
(üblicherweise die Anwender-bekannte Identifikation des
referenzierenden BOs) werden
* in der Methode
'isReferenced()' mit Werten versorgt.
* Rollback ist
zwar nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
rollbackDBConnection();
return
;
}
else
{
/*
BO kann deaktiviert werden.
* Ein DBA-Set-Objekt erstellen
mit dem alle Datensätze für den ObjectID selektiert werden.
*/
application_dbtable
_DBA_Set
struct
application_dbtable
_DBA_Set
=
new
application_dbtable
_DBA_Set();
/*
Datenbank-Zugriff über das DBA_Set-Objekt ausführen. */
structapplication_dbtable
_DBA_Set.selectAllByObjectID(
structDBCon
,
this
.
ObjectID
);
/*
Prüfen ob der DB-Zugriff fehlerfrei war. */
if
(struct
application_dbtable
_DBA_Set.ErrorMsg.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler;
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen. */
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
= struct
application_dbtable
_DBA_Set.ErrorMsg;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden. */
rollbackDBConnection();
return
;
}/*
Kein DB-System-Fehler bei der Datenbank-Operation; Set mit den
Datensätzen
* weiter bearbeiten.
* Dazu
Hilf-Variable für die Bearbeitung des Vector definieren.
*/
int
intDBA_Set_Size
= struct
application_dbtable
_DBA_Set.
vecRecordSet
.size();
int
intDBA_Set_Index
= 0;
/*
Ein BOS definieren dessen Methoden später für das
ordnungsgemäße 'Beenden' eines
* Datensatzes
verwendet werden können. */
application_entity
_BOS
struct
application_entity
_BOS
=
new
application_entity
_BOS(
structJSBS_MinimalParameters
,
structDBCon
);
/*
Datums-Werte die für Vergleiche gebraucht werden im
java.sql.Date-Format
* definieren bzw. gleich umwandeln.
*/
java.sql.Date dteWorkDate =
new
java.sql.Date(
structJSBS_MinimalParameters
.
calWorkDate
.getTime().getTime());
java.sql.Date dteReadValidTill; /*
In einer for-Schleife jeden Datensatz untersuchen und bei Bedarf
'beenden'. */
for
(intDBA_Set_Index
= 0; intDBA_Set_Index < intDBA_Set_Size; intDBA_Set_Index++) {
/*
Indizierten Datensatz aus dem Set 'holen'. */
struct
application_dbtable
_DBA
=
(
application_dbtable
_DBA)
structapplication_dbtable
_DBA_Set.
vecRecordSet
.elementAt(intDBA_Set_Index);
/*
Letzten Tag der Gültigkeit in ein Format umwandeln das sich
leichter vergleichen lässt. */
dteReadValidTill =
struct
application_dbtable
_DBA
.
ValidTill
;
/*
Nur jene Datensätze deaktivieren die nach dem aktuellen Datum
enden. */
if
(struct
application_dbtable
_DBA_Set.endsAfterWorkDate(dteWorkDate,
dteReadValidTill)) {
/*
Werte des DBA in das vorher 'konstruierte' BOS übernehmen.
*
Grund: In der BOS-Klasse sind schon die Methoden implementiert, die
die Gültigkeit eines
* Datensatzes ordnungsgemäß
beenden. */
structapplication_entity
_BOS.getDBAAttributes(
struct
application_dbtable
_DBA
);
/*
Status-Code initialisieren.
* Diese Variable wird bei einer
'internen' Methode nicht initialisiert. */
structapplication_entity
_BOS.
StatusCode
=
CONST_OK
;
/*
Ende der Gültigkeit des Datensatzes abhängig vom aktuellen
Datum setzen. */
structapplication_entity
_BOS.
ValidTill
=
JSBS_BO_Services.getNewValidTill(structJSBS_MinimalParameters
);
/*
Methode zum Ändern der Werte aufrufen. */
structapplication_entity
_BOS.internalUpdate();
/*
Prüfen ob beim 'Update' ein Fehler aufgetreten ist. */
if
(struct
application_entity
_BOS.
StatusCode
!=
CONST_OK
)
{
/*
Fehler-Code und -Nachricht auf die Variablen dieses BO übernehmen.
*/
this
.
StatusCode
=
struct
application_entity
_BOS.
StatusCode
;
this
.
StatusMsg
=
struct
application_entity
_BOS.
StatusMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden. */
rollbackDBConnection();
return
;
}/*
Methode zum Einfügen des Datensatzes, der die Information, wer
das BO deaktiviert
* hat, enthält. */
structapplication_entity
_BOS.internalInsert(
false
,
JSBS_BO_Services.getNewValidFrom(structJSBS_MinimalParameters
),
JSBS_BO_Services.getNewValidTill(structJSBS_MinimalParameters
));
/*
Prüfen ob beim 'Insert' ein Fehler aufgetreten ist. */
if
(struct
application_entity
_BOS.
StatusCode
!=
CONST_OK
)
{
/*
Fehler-Code und -Nachricht auf die Variablen dieses BO übernehmen.
*/
this
.
StatusCode
=
struct
application_entity
_BOS.
StatusCode
;
this
.
StatusMsg
=
struct
application_entity
_BOS.
StatusMsg
;
/* Rollback
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden. */
rollbackDBConnection();
return
;
}/*
Ende des 'if' zum Bearbeiten noch gültiger Datensätze.
*/
}/*
Ende der 'for'-Schleife. */
}/*
Alle Änderungen auf der Datenbank ohne Fehler; Commit
ausführen.
* Anschließend Methode beenden.
*/
commitDBConnection();
return
;
}
}
/*
-----------------------------
* METHODE zum Prüfen
ob auf dieses BO in einem anderen BO eine Referenz vorhanden ist.
*
Diese Methode dient dazu, zu prüfen ob das BO deaktiviert werden
darf oder nicht
* deaktiviert werden darf weil sonst in
einem anderen BO eine Inkonsistenz entsteht. */
private
boolean
isReferenced()
{
/*
* Voraussetzung für diesen Muster-Code ist, dass
im referenzierenden BO (implementiert in
* der Klasse
'BOS-Set') eine Methode vorhanden ist, die alle zum aktuellen
Datum und in Zukunft
* gültigen BOs selektiert, die das
hier zu löschende BO als Fremdschlüssel referenzieren.
*//*
* Der folgende Muster-Code muss für jede
referenzierende BO-Klasse implementiert (das heisst
*
kopiert und adaptiert) werden. *//*
*
***** FOLGENDER MUSTER-CODE MUSS GELÖSCHT WERDEN WENN NICHT AUF
REFERENZEN GEPRÜFT WIRD. *****
* Oder er kann für
das Prüfen einer weiteren Referenz kopiert werden. */ /*
* Ein BOS-Set definieren mit dem später geprüft
werden kann, ob eine Referenz auf das hier
* zu
deaktivierende BO vorhanden ist. */
referencing_app_entity
_BOS_Set
struct
referencing_app_entity
_BOS_Set
=
new
referencing_app_entity
_BOS_Set(
structJSBS_MinimalParameters
,
structDBCon
,
true
);
/*
Methode zum Selektieren der Liste mit den referenzierenden BOs. */
structreferencing_app_entity
_BOS_Set.selectValidAndFutureBy
Variables
(
this
.
ReferencedVariable1
,
this
.
ReferencedVariable2
);
/*
* Prüfen
ob die Datenbank-Operation fehlerfrei war; dazu den Status-Code des
* BOC-Set abfragen. */
switch
(struct
referencing_app_entity
_BOS_Set.
StatusCode
)
{
case
CONST_OK
:
/*
Dieses BO wird referenziert; zur Sicherheit prüfen ob auch
wirklich BOs
*
im Vector vorhanden sind. */
if
(struct
referencing_app_entity
_BOS_Set.
vecRecordSet
.size()
> 0) {
/*
Entsprechenden Status-Code setzen; dieser ist in der zugehörigen
'BO-Klasse'
*
definiert. */
this
.
StatusCode
=
CONST_DEAKTIVATE_INHIBIT_REASON_
Reason
;
/*
Zur Information des Anwenders die Anwender-bekannte Identifikation
aus dem ersten
*
BO der Liste extrahieren und in der Status-Message zurückliefern.
*/
referencing_app_entity
_BO
struct
referencing_app_entity
_BO
=
(
referencing_app_entity
_BO)
struct
referencing_app_entity
_BOS_Set.
vecRecordSet
.elementAt(0);
this
.
StatusMsg
= struct
referencing_app_entity
_BO.
UserKnownKeyVariable1
+
"/"
+
struct
referencing_app_entity
_BO.
UserKnownKeyVariable2
;
/* 'true'
als Flag zurückliefern damit dieses BO nicht deaktiviert wird.
*/
return true
;
}
break
;
case
CONST_NOT_FOUND
:
/*
Dieses BO wird nicht referenziert;
*
dieses 'case' ist nur vorhanden damit nicht das 'default' zum Zug kommt wenn
*
kein Datensatz in der Liste ist. */
break
;
default
:
/* Ein
anderer Fehler ist beim Selektieren aufgetreten.
*
Status-Code und Status-Message in die Variablen dieses BO übernehmen
und
* 'true' zurückliefern damit (zur Sicherheit)
dieses BO nicht deaktiviert wird. */
this
.
StatusCode
= struct
referencing_app_entity
_BOS_Set.
StatusCode
;
this
.
StatusMsg
= struct
referencing_app_entity
_BOS_Set.
StatusMsg
;
return true
;
}
/*
*
***** ENDE DES ZU LÖSCHENDEN ODER KOPIERENDEN MUSTER-CODE.
*****
*/
/*
-----------
* Wenn notwendig hier weitere Prüfungen ob
dieses BO referenziert wird einfügen.
*
Dazu den Muster-Code von oben kopieren.
*/
/*
* -----------
*/
/*
*
Wenn diese Methode nicht mit einem Algorithmus gefüllt wird oder
die Abfrage auf,
* Referenzen kein 'true' ergibt, dann wird
'false' zurückgeliefert.
* das ist das Signal, dass
dieses BO nicht von einem anderen BO referenziert wird.
*/
return
false
;
}
/* ---------------------
* METHODE zum Prüfen auf Konsistenz der Daten
dieses BO.
*
*
Diese Methode ist dazu gedacht, eine Prüfung auf Korrektheit der
Werte dieses BO durchzuführen
*
bevor die Daten gespeichert werden.
*
Eine Prüfung der Konsistenz der Daten ist dann erforderlich wenn
nicht sicher gestellt werden kann,
*
dass bei der Eingabe der Daten die Prüfungen durchgeführt
werden oder wenn die Prüfungen so komplex
*
sind, dass sie bei der Eingabe nicht vollständig durchgeführt
werden können.
*
*
Wenn die Prüfregeln nicht erüllt werden kann als genereller
Status-Code die Konstante
*
CONST_INCONSISTENT_DATA (aus der Basisklasse JSBS_BO)
verwendet
werden oder es können in dieser Klasse
*
detailliertere Konstante für den Status-Code definiert
werden.
*
*
Prüf-Algorithmen, die Werte anderer Business-Objects nicht
erfordern (und damit auf die Datenbank
*
zugreifen müssen) soll der Algorithmus dafür in der
Generellen Klasse für das BO implementiert
*
werden. */
public boolean
isConsistentData()
{
/*
*
Abfragen ob in der (geerbten) Generellen Klasse für das BO die
Prüfregeln 'nicht bestanden'
*
wurden. */
if
(!
super
.isConsistentData())
return
false
;
/*
* Anschließend ist der Algorithmus. */
/*
*
Wenn in dieser Methode keine Prüfungen durchgeführt werden,
werden die Daten
*
als 'konsistent' betrachtet. */
return
true
;
}
}
Die Datenbank-Tabelle Parameter ist dafür vorgesehen, BO abzuspeichern für deren Klasse keine größeren Mengen erwartet werden.
Typisch
dafür sind Einstellungen für das Anwendungsprogramm oder
Werte für Kategorien (z.B. die Branche von Kunden).
Im
JavaScout Base-System (JSBS)
ist eine JSBS_Parameter_DBA
– Klasse für den Low-Level Zugriff auf die DB-Tabelle
'Parameter' implementiert, die Zugriffe auf diese Tabelle
('Parameter') implementiert hat.
Die
Unterschiede zum Standard-Muster-Code sind aber so gering, dass nicht
der gesamte Code gelistet wird – es wird bei den betreffenden
Anleitungen der jeweilige Muster-Teil, der bei Verwendung der
Datenbank-Tabelle 'Parameter' passend ist, beschrieben.
Anleitung
zur Adaptierung
Am leichtesten
funktioniert die Anpassung des Muster-Codes an die eigenen
Erfordernisse durch Kopieren des Muster-Codes und Verwendung von
Edit
> Find/Replace...
.
|
|
Für
'Platzhalter', die nur einmalig im Muster-Code vorkommen ist die
'Find'-Funktion hilfreich zum Finden der beschriebenen 'Platzhalter'.
Änderung
des Namens der Java-Packages der Anwendung
package
application_package
.bos;
.
. . . .
. . . . ./*
*
Geerbte Generelle Klasse des BO. */import
application_package
.bo.*;
/*
DBA-Klasse für den Zugriff auf die DB-Tabelle. */
import
application_package
.dba.*;
/**
D
er
Name dieses Packages kommt in der ersten Zeile des Muster-Codes und -
wenn den Namenskonventionen gefolgt wurde – noch weitere 2 Mal
in den Namen der Packages mit den Generellen Klassen der BO und den
DBA-Klassen vor.
Bei
Verwendung der DB-Tabelle 'Parameter' wird das DBA aus den JavaScout
Basisklassen (JSBS_Parameter_DBA)
verwendet:
/*
*
Geerbte Generelle Klasse des BO. */import
application_package
.bo.*;
/*
DBA-Klasse für den Zugriff auf die DB-Tabelle. */
import
js_base.dba.*;
/**
Adaptieren
des Kommentars
'Kein Kommentar
ist besser als ein falscher'
.
Aus
diesem Grund ist im Muster-Code auch keine Hintergrund-Information
über Entwurfs-Entscheidungen für das BOS vorhanden.
Meiner
Erfahrung nach ist es ausreichend für die Beschreibung der
Variablen des BO auf die Generelle Klasse für das BO zu
verweisen.
Die einzelnen Methoden der BOS-Klasse sind innerhalb
des Codes kommentiert.
Änderung
des Namens der Klasse
*/
public
class
application_entity
_BOS
extends
application_entity
_BO
{
/*
Dieser
Name muss mit dem Namen der Klasse übereinstimmen, der beim
Eröffnen der Klasse gewählt wurde.
Der
Name der Klasse kommt mehrmals im gesamten Code vor.
Deswegen
empfehle ich, mit 'Find/Replace' alle Platzhalter
application_entity
_BO
im
Muster-Code durch den gewählten Klassen-Namen zu
ersetzen.
application_entity
_BO
als
Vergleichswert wird deswegen gewählt weil damit auch die
Variable für die geerbte Klasse geändert wird.
DBA-Objekt als
Variable definieren
/*
* ---------------------
* Die
folgende Variable ist das DBA-Objekt für den Zugriff auf die
DB-Tabelle.
* Dieses DBA-Objekt wird mehrfach gebraucht
und deswegen global in der Klasse definiert. */
private
application_dbtable
_DBA
struct
application_dbtable
_DBA
=
new
application_dbtable
_DBA
();
Als
Variable ist auch das DBA- (DataBase-Access) Objekt für den
Zugriff auf eine Datenbank-Tabelle definiert.
Der Name der Klasse
kommt mehrmals im gesamten Code vor.
Deswegen empfehle ich, mit
'Find/Replace' alle Platzhalter application_dbtable
_DBA
im
Muster-Code durch den gewählten Klassen-Namen zu ersetzen.
Bei
BOS für komplexere Aufgaben können auch andere DBA-Klassen
notwendig sein. Der Code dafür ist dann einzeln an den richtigen
Stellen zu implementieren.
Bei
Verwendung der DB-Tabelle 'Parameter' wird das DBA aus den JavaScout
Basisklassen (JSBS_Parameter_DBA)
verwendet:
/*
* ---------------------
* Die
folgende Variable ist das DBA-Objekt für den Zugriff auf die
DB-Tabelle.
* Dieses DBA-Objekt wird mehrfach gebraucht
und deswegen global in der Klasse definiert. */
private
JSBS_Parameter_DBA
structJSBS_Parameter_DBA
=
new
JSBS_Parameter_DBA
();
Nachdem
diese Variable mehrmals innerhalb des Codes vorkommt, ist es sinnvoll
alle 'Verwendungen' mit 'Find/Replace...' zu ändern:
Find:
application_dbtable
_DBA
/
Replace:
JSBS_Parameter_DBA
.
Methode
setDBAAttributes(...)
adaptieren
/*
* METHODE
zum Übertragen der Attribute auf das haupt-zugeordnete
DBA-Objekt. */
private
void
setDBAAttributes(
application_dbtable
_DBA
parm
application_dbtable
_DBA)
{
/*
* Aufruf
der Methode der geerbten Klasse (Superklasse) um die 'Common
Attributes'
* zu kopieren.
*/
super
.setCommonDBAAttributes(parm
application_dbtable
_DBA);
/*
* Übertragen
der geschäfts-spezifischen Werte dieses BO.
*/
parmapplication_dbtable
_DBA.
VariableName
=
this
.
BO_VariableName
;
}
Der
Platzhalter für den Namen des DBA-Objekts
(
application_dbtable
_DBA
)
ist durch den gültigen Namen zu ersetzen.
Dies ist
wahrscheinlich schon erfolgt, wenn im Abschnitt DBA-Objekt
als Variable definieren
ein
'Find/replace' über den gesamten Muster-Code ausgeführt
wurde.
Für
jede Variable der DBA-Klasse ist zu definieren, von welcher Variable
der BO-Klasse der Wert übertragen wird.
Die Variable des BO
ist in der geerbten 'Generellen Klasse' des BO definiert.
Bei
Verwendung der DB-Tabelle 'Parameter' – und dem zugehörigen
DBA aus den JavaScout Basisklassen (JSBS_Parameter_Set_DBA)
- sind folgende Richtlinien zu beachten:
Der
Parameter-Name, mit dem Datensätze dieses BO auf der DB-Tabelle
'Parameter' gekennzeichnet sind, muß an die Variable
ParameterName
des
DBA-Objektes zugewiesen werden.
Der Parameter-Name wurde als
Konstante (CONST_PARAMETER_NAME
)
in der Generellen Klasse für das BO definiert und von dieser
Klasse (BOS) geerbt.
* zu
kopieren.
*/
super
.setCommonDBAAttributes(parmJSBS_Parameter_DBA);
/*
* Übertragen
des Parameter-Namens der die Datensätze dieses BO
identifiziert. */
parmJSBS_Parameter_DBA.
ParameterName
=
application_entity
_BO.
CONST_PARAMETER_NAME
;
/*
* Übertragen
der geschäfts-spezifischen Werte dieses BO. */
Die
allgemein nutzbaren Variablen der
JSBS_Parameter_DBA
-Klasse
sind vom Typ (Klasse) 'String' und haben die Variablen-Namen
Value01
bis
Value20
.
Dabei
sind Value01
bis
Value05
im
DB-Tabellen-Index für die Anwender-bekannte Identifikation
enthalten.
* Übertragen
des Parameter-Namens der die Datensätze dieses BO
identifiziert. */
parmJSBS_Parameter_DBA.
ParameterName
=
this
.
CONST_PARAMETER_NAME
;
/*
* Übertragen
der geschäfts-spezifischen Werte dieses BO.
*//*
* Anschließend
ein Beispiel für das Übertragen einer Zeichenkette
(String). */
parmJSBS_Parameter_DBA.
Value
XX
=
this
.
BO_VariableNameYY
;
/*
* Variablen
des BO mit numerischem Wert müssen auf eine Zeichenkette
(String)
* umgewandelt werden – dazu werden die
Methoden der JavaScout-Basisklassen verwendet. *//*
* Bei
Werten mit Stellen hinter dem 'Komma' muss als Dezimal-Trennzeichen
der Character '.'
* (Punkt) verwendet werden. Auch die
Angabe der Stellen hinter dem Komma ist notwendig.
* Im
nachfolgenden Beispiel werden 2 Stellen hinter dem Komma definiert.
*/
parmJSBS_Parameter_DBA.
Value
XX
=
JSBS_Formatter.toFormattedString(
this
.
BO_VariableNameYY
,
'.'
,
2
);
/*
* Bei
ganzzahligen Werten ist nur der Wert des BO als Parameter
erforderlich. */
parmJSBS_Parameter_DBA.
Value
XX
=
JSBS_Formatter.toFormattedString(
this
.
BO_VariableNameYY
);
}
Die
Kenntnis, welche Attribute der DB-Tabelle in einem Index enthalten
sind, hilft bei der Abschätzung der Zugriffszeit.
Es ist zu
empfehlen, Variablen des BO nach denen 'gesucht' wird, den im Index
enthaltenen Attributen der DB-Tabelle zuzuordnen.
Umgekehrt
sollen Variablen des BO nach denen nicht gesucht wird, Attributen
zuzuordnen die nicht im Index der DB-Tabelle enthalten sind,
zuzuordnen.
Grund dafür ist, dass bei Änderung des
Wertes eines im Index enthaltenen Attributs auch der Wert im Index
geändert und der Index neu sortiert werden muss. Das bedeutet
zusätzlichen Zeitaufwand beim Speichern von Daten.
Methode
store()
adaptieren
/*
* Speichern eines neuen Business-Object
angefordert.
* Prüfen, dass noch kein BO mit der
gleichen Anwender-bekannten Identifikation existiert.
*/
boolean
locbolDataSetExists
=
struct
application_dbtable
_DBA
.selectByUserKnownKey(
structDBCon
,
structJSBS_MinimalParameters
,
this
.
KeyVariable_1
,
this
.
KeyVariable_2
);
if
(locbolDataSetExists)
{
/* BO
mit der gleichen Anwender-bekannten Identifikation existiert bereits
auf der DB-Tabelle.
* Fehler an aufrufende Methode
signalisieren, Rollback einleiten und Methode beenden.
*/
StatusCode
=
CONST_DUPLICATE_KEY
;
StatusMsg
=
""
;
rollbackAndCloseDBConnection(bol_structDBConOpenedInThisMethod,
bol_autocommit);
return
;
}
else
{
/* Kein
entsprechender Datensatz gefunden; könnte aber auch ein Fehler
beim DB-Zugriff sein. */
if
(
struct
application_dbtable
_DBA
.
ErrorMsg
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler.
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
CONST_DB_SYSTEM_ERROR
;
StatusMsg
=
struct
application_dbtable
_DBA
.
ErrorMsg
;
/* Rollback
einleiten und Methode beenden.
*/
rollbackAndCloseDBConnection(bol_structDBConOpenedInThisMethod,
bol_autocommit);
return
;
}
}/*
* Wenn
die Verarbeitung bis hierher gelaufen ist, existiert kein BO mit
der
* gleichen Anwender-bekannten Identifikation und
die DB-Abfrage danach war fehlerfrei.
Der
Platzhalter für den Namen des DBA-Objekts
(
application_dbtable
_DBA
)
ist durch den gültigen Namen zu ersetzen.
Dies ist
wahrscheinlich schon erfolgt, wenn im Abschnitt DBA-Objekt
als Variable definieren
ein
'Find/replace' über den gesamten Muster-Code ausgeführt
wurde.
Bei
Verwendung der DB-Tabelle 'Parameter' – und dem zugehörigen
DBA aus den JavaScout Basisklassen (JSBS_Parameter_DBA)
– ist die Adaptierung des folgenden Codes im Abschnitt
Methode
store()
adaptieren
bei Verwendung des
JSBS_Parameter_DBA
beschrieben.
Bei
der Abfrage nach einem bereits existierenden DBA-Objekt mit
Anwender-bekannter
Identifikation
struct
application_dbtable
_DBA
.selectByUserKnownKey(
structDBCon
,
structJSBS_MinimalParameters
,
this
.
KeyVariable_1
,
this
.
KeyVariable_2
);
sind
die Parameter, die die Schlüssel-Werte übergeben,
entsprechend zu adaptieren.
Die folgenden
Adaptierungen der BO- und BOS-Klassen wurden schon durchgeführt,
wenn Sie das 'Find/Replace' wie unter
Änderung
des Namens der Klasse und der 'Constructor'-Methoden
beschrieben
ausgeführt haben.
* Zum
Lesen des Vergleichs-BOS wird ein neues BOS 'konstruiert' und dabei
die bestehende
* DB-Connection als Parameter übergeben.
*/
application_entity
_BOS
existing
application_entity
_BOS
=
new
application_entity
_BOS(
structJSBS_MinimalParameters
,
structDBCon
);
/*
* Datensatz
mit dem DatasetID lesen; das bringt den Datensatz der vor einiger
Zeit
* gelesen wurde. */
Der
obige Code-Teil ist nur ein Beispiel; die Verwendung von Objekten der
BO- und BOS-Klassen kommt mehrmals vor.
Methode
store()
adaptieren
bei Verwendung des
JSBS_Parameter_DBA
Bei
der Abfrage nach einem bereits existierenden DBA-Objekt mit
Anwender-bekannter Identifikation ist der Parameter-Name ein Teil des
Schlüssels und als Parameter beim Aufruf der Methode zu
übergeben.
Als
weitere Parameter können bis zu 5 Werte übergeben werden.
Diese Werte entsprechen den Attributen Value01
bis
Value05
der
Datenbank-Tabelle.
Im folgenden Muster-Code werden 2 Variablen des
BO als Schlüssel-Werte als Parameter beim Aufruf der Methode
übergeben.
Die Methode akzeptiert die Übergabe von 0
bis 5 Werten als Anwender-bekannte
Identifikation.
structJSBS_Parameter_DBA
.selectByUserKnownKey(
structDBCon
,
structJSBS_MinimalParameters
,
CONST_PARAMETER_NAME
,
this
.
KeyVariable_1
,
this
.
KeyVariable_2
);
Methode
selectByUserKnownKey(...)
adaptieren
/*
* METHODE
zum Selektieren des aktuell gültigen Datensatzes mit
der
* Anwender-bekannten Identifikation.
* 'Aktuell
gültig' bedeutet, dass die Gültigkeit des Datensatzes mit
dem
* im Minimalen Set von Parametern übergebenen
Arbeitsdatum übereinstimmt.
* Es kann nur ein
Datensatz gefunden werden – dieser ist Teil eines
Business-Objektes (BO). */
public
synchronized
void
selectByUserKnownKey(String
parm
KeyVariable_1
,
String parm
KeyVariable_2
)
{
/* Lokales
Flag setzen, dass in dieser Methode keine Änderungen auf der
DB-Tabelle erfolgen.
* Damit erfolgt auch kein
'commit' durch den implementierten Code.
In
der Methoden-Deklaration sind die Parameter, die die
Anwender-bekannte Identifikation bilden, zu adaptieren.
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
struct
application_dbtable
_DBA
.selectByUserKnownKey(
structDBCon
,
structJSBS_MinimalParameters
,
parm
KeyVariable_1
,
parm
KeyVariable_2
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
Die
in der Methoden-Deklaration übernommenen Parameter werden beim
Aufruf der zugehörigen Methode des DBA-Objektes wieder als
Parameter übergeben.
Der
Platzhalter für den Namen des DBA-Objekts
(
application_dbtable
_DBA
)
ist durch den gültigen Namen zu ersetzen.
Das
DBA-Objekt kommt mehrmals in der Methode
selectByUserKnownKey(...)
vor;
im obigen Code-Ausschnitt wird nur ein Auftreten gezeigt.
Das
Adaptieren ist wahrscheinlich schon erfolgt, wenn im Abschnitt
DBA-Objekt
als Variable definieren
ein
'Find/Replace' über den gesamten Muster-Code ausgeführt
wurde.
Methode
selectByUserKnownKey(...)
adaptieren
bei Verwendung des
JSBS_Parameter_DBA
Bei
der Abfrage nach einem bereits existierenden DBA-Objekt mit
Anwender-bekannter Identifikation ist der Parameter-Name ein Teil des
Schlüssels und als Parameter beim Aufruf der Methode zu
übergeben.
Als
weitere Parameter können bis zu 5 Werte übergeben werden.
Diese Werte entsprechen den Attributen Value01
bis
Value05
der
Datenbank-Tabelle.
Im folgenden Muster-Code werden 2 Variablen des
BO als Schlüssel-Werte als Parameter beim Aufruf der Methode
übergeben.
Die Methode akzeptiert die Übergabe von 0
bis 5 Werten als Anwender-bekannte Identifikation.
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
structJSBS_Parameter_DBA
.selectByUserKnownKey(
structDBCon
,
structJSBS_MinimalParameters
,
CONST_PARAMETER_NAME
,
parmKeyVariable_1
,
parm
KeyVariable_2
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
Die
in der Methoden-Deklaration übernommenen Parameter werden beim
Aufruf der zugehörigen Methode des DBA-Objektes wieder als
Parameter übergeben.
Das
DBA-Objekt kommt mehrmals in der Methode
selectByUserKnownKey(...)
vor;
im obigen Code-Ausschnitt wird nur das Auftreten beim Ausführen
der DBA-Methode gezeigt.
Das
Adaptieren ist wahrscheinlich schon erfolgt, wenn im Abschnitt
DBA-Objekt
als Variable definieren
ein
'Find/Replace' über den gesamten Muster-Code ausgeführt
wurde.
Methode
selectNext(...)
und
selectPrevious(...)
adaptieren
Als
Code-Beispiele werden jene aus der Methode
selectNext(...)
verwendet.
Die
Änderung in der Methode
selectPrevious(...)
erfolgt
analog.
/*
* METHODE
zum Selektieren des Datensatzes mit jener Anwender-bekannten
Identifikation,
* die in der Sortier-Reihenfolge nach
den Werten, die als Parameter übergeben
werden,
* auftreten.
* Dabei kann nur ein
Datensatz gefunden werden. */
public
synchronized
void
selectNext(
String
parm
KeyVariable_1
,
String
parm
KeyVariable_2
,
String
parm
KeyVariable_3
)
{
/* Lokales
Flag setzen, dass in dieser Methode keine Änderungen auf der
DB-Tabelle erfolgen.
In
der Methoden-Deklaration sind die Parameter, die die
Anwender-bekannte Identifikation bilden, zu adaptieren.
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
struct
application_dbtable
_DBA
.selectNext(
structDBCon
,
structJSBS_MinimalParameters
,
parmKeyVariable_1
,
parm
KeyVariable_2
,
parm
KeyVariable_3
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
Die
in der Methoden-Deklaration übernommenen Parameter werden beim
Aufruf der zugehörigen Methode des DBA-Objektes wieder als
Parameter übergeben.
Der
Platzhalter für den Namen des DBA-Objekts
(
application_dbtable
_DBA
)
ist durch den gültigen Namen zu ersetzen.
Das
DBA-Objekt kommt mehrmals in der Methode
selectNext(...)
bzw.
selectPrevious(...)
vor;
im obigen Code-Ausschnitt wird nur ein Auftreten gezeigt.
Das
Adaptieren ist wahrscheinlich schon erfolgt, wenn im Abschnitt
DBA-Objekt
als Variable definieren
ein
'Find/Replace' über den gesamten Muster-Code ausgeführt
wurde.
Methode
selectNext(...)
und
selectPrevious(...)
adaptieren
bei Verwendung des
JSBS_Parameter_DBA
Bei
der Abfrage nach einem bereits existierenden DBA-Objekt mit
Anwender-bekannter Identifikation ist der Parameter-Name ein Teil des
Schlüssels und als Parameter beim Aufruf der Methode zu
übergeben.
Als
weitere Parameter können bis zu 5 Werte übergeben werden.
Diese Werte entsprechen den Attributen Value01
bis
Value05
der
Datenbank-Tabelle.
Im folgenden Muster-Code werden 3 Variablen des
BO als Schlüssel-Werte als Parameter beim Aufruf der Methode
übergeben.
Die Methode akzeptiert die Übergabe von 0
bis 5 Werten als Anwender-bekannte Identifikation.
/*
* Datenbank-Zugriff über das DBA-Objekt
ausführen. */
if
(
structJSBS_Parameter_DBA
.selectNext(
structDBCon
,
structJSBS_MinimalParameters
,
CONST_PARAMETER_NAME
,
parm
KeyVariable_1
,
parm
KeyVariable_2
,
parm
KeyVariable_3
))
{
/* Datensatz
existiert und wurde fehlerfrei gelesen.
Die
in der Methoden-Deklaration übernommenen Parameter werden beim
Aufruf der zugehörigen Methode des DBA-Objektes wieder als
Parameter übergeben.
Das
DBA-Objekt kommt mehrmals in der Methode
selectNext(...)
bzw.
selectPrevious(...)
vor;
im obigen Code-Ausschnitt wird nur das Auftreten beim Ausführen
der DBA-Methode gezeigt.
Das
Adaptieren ist wahrscheinlich schon erfolgt, wenn im Abschnitt
DBA-Objekt
als Variable definieren
ein
'Find/Replace' über den gesamten Muster-Code ausgeführt
wurde.
Methode
deactivate()
adaptieren
/*
BO kann deaktiviert werden.
* Ein DBA-Set-Objekt erstellen
mit dem alle Datensätze für den ObjectID selektiert werden.
*/
application_dbtable
_DBA_Set
struct
application_dbtable
_DBA_Set
=
new
application_dbtable
_DBA_Set;
/*
Datenbank-Zugriff über das DBA_Set-Objekt ausführen. */
structapplication_dbtable
_DBA_Set.selectValidAndFutureByObjectID(
structDBCon
,
this
.
ObjectID
)
{
/*
Prüfen ob der DB-Zugriff fehlerfrei war. */
if
(struct
application_dbtable
_DBA_Set.
ErrorMessage
.length()
> 0) {
/* DBA-Objekt
meldet einen Fehler;
Zum
Ermitteln aller aktuell und in Zukunft gültigen Datensätze
wird die passende Methode für die DBA- (DataBase-Access-) Klasse
verwendet.
Der
Platzhalter für den Namen des DBA-Objekts
(
application_dbtable
_DBA
)
ist durch den gültigen Namen zu ersetzen.
Das
DBA-Objekt kommt mehrmals in der Methode vor; im obigen
Code-Ausschnitt wird nur ein Auftreten gezeigt.
Das
Adaptieren ist wahrscheinlich schon erfolgt, wenn im Abschnitt
DBA-Objekt
als Variable definieren
ein
'Find/Replace' über den gesamten Muster-Code ausgeführt
wurde.
/*
Ein BOS definieren dessen Methoden später für das
ordnungsgemäße 'Beenden' eines
* Datensatzes
verwendet werden können. */
application_entity
_BOS
struct
application_entity
_BOS
=
new
application_entity
_BOS(
structJSBS_MinimalParameters
,
structDBCon
);
/*
Datums-Werte die für Vergleiche gebraucht werden im
java.sql.Date-Format
Zum
Ermitteln und setzen des neuen 'Gültig-Bis'-Datums werden die
passenden Methoden für die BO und BOS-Klasse verwendet.
Der
Platzhalter für den Namen der BO- und BOS-Objekte
(
application_entity
_BO
)
ist durch den gültigen Namen zu ersetzen.
BO-
und BOS-Objekte kommen mehrmals in der Methode vor; im obigen
Code-Ausschnitt wird nur ein Auftreten gezeigt.
Das
Adaptieren ist wahrscheinlich schon erfolgt, wenn im
Abschnitt Änderung
des Namens der Klasse und der 'Constructor'-Methoden
ein
'Find/Replace' über den gesamten Muster-Code ausgeführt
wurde.
Methode
isReferenced()
adaptieren
Voraussetzung
für das Implementieren der Prüfungen in dieser Methode
ist, dass eine Methode zum Selektieren der referenzierenden
Business-Objects implementiert ist (Beschreibung im
Dokument
Muster-Code
für ein BOS_Set (Liste mit Business-Objects,
Server-Side-Klasse)
)
und eine zugehörige Konstante für den Status-Code
definiert ist (Beschreibung im Dokument
Muster-Code
für ein BO (Generelle Klasse eines Business-Object)
).
Wenn
nicht auf eine Referenz geprüft werden muss, dann ist der Code
innerhalb der Hinweise im Kommentar zu löschen.
Im
Muster-Code ist die Prüfung auf die mögliche
Referenzierung durch Business-Objects
einer
anderen
Klasse dargestellt.
Im 'wirklichen Leben' können
wahrscheinlich Business-Objects mehr als einer anderen Klasse eine
Referenz auf dieses BO enthalten.
Für
jede Klasse eines möglicherweise referenzierenden BO ist der
Muster-Code für die Prüfung zu kopieren und zu adaptieren.
/*
* Ein BOS-Set definieren mit dem später geprüft
werden kann, ob eine Referenz auf das hier
* zu
deaktivierende BO vorhanden ist. */
referencing_app_entity
_BOS_Set
struct
referencing_app_entity
_BOS_Set
=
new
referencing_app_entity
_BOS_Set(
structJSBS_MinimalParameters
,
structDBCon
,
true
);
/*
Methode zum Selektieren der Liste mit den referenzierenden BOs. */
structreferencing_app_entity
_BOS_Set.selectBy
Variables
(
this
.
ReferencedVariable1
,
this
.
ReferencedVariable2
);
/*
* Prüfen
ob die Datenbank-Operation fehlerfrei war; dazu den Status-Code des
* BOC-Set abfragen. */
switch
(
struct
referencing_app_entity
_BOS_Set
.
StatusCode
)
{
Die
Klasse der möglicherweise referenzierenden BO, die Methode zum
selektieren der referenzierenden BO und die Parameter der Methode
müssen angepasst werden.
Die
Klasse und das Objekt kommen mehrmals in der Methode vor; im obigen
Code-Ausschnitt wird das Auftreten nur zu Beginn des Muster-Codes
gezeigt.
if
(
struct
referencing_app_entity
_BOS_Set
.
vecRecordSet
.size()
> 0) {
/*
Entsprechenden Status-Code setzen; dieser ist in der zugehörigen
'BO-Klasse'
*
definiert. */
this
.
StatusCode
=
CONST_DEAKTIVATE_INHIBIT_REASON_
Reason
;
/*
Zur Information des Anwenders die Anwender-bekannte Identifikation
aus dem ersten
*
BO der Liste extrahieren und in der Status-Message zurückliefern.
*/
referencing_app_entity
_BO
struct
referencing_app_entity
_BO
=
(
referencing_app_entity
_BO)
referencing_app_entity
_BOS_Set
.
vecRecordSet
.elementAt()
;
this
.
StatusMsg
=
referencing_app_entity
_BO
.
UserKnownKeyVariable1
+
"/"
+
referencing_app_entity
_BO
.
UserKnownKeyVariable2
;
/* 'true'
als Flag zurückliefern damit dieses BO nicht deaktiviert wird.
*/
return true
;
}
Der
zugehörige Status-Code und die Anwender-bekannte Identifikation
des ersten referenzierenden BO, der in der Status-Message zurück
geliefert wird, sind zu adaptieren.
Wenn
auf eine Referenz geprüft wird, dann wird die Anweisung für
das Zurückliefern von
false
am
Ende des Codes nicht mehr erreicht und der Compiler meldet dies als
Fehler.
Zur Vermeidung des Fehlers kann die Anweisung gelöscht
oder 'auskommentiert' werden.
/*
*
***** ENDE DES ZU LÖSCHENDEN ODER KOPIERENDEN MUSTER-CODE.
*****
*/
/*
-----------
* Wenn notwendig hier weitere Prüfungen ob
dieses BO referenziert wird einfügen. *//*
* -----------
*/
/*
*
Wenn diese Methode nicht mit einem Algorithmus gefüllt wird,
wird 'false' zurückgeliefert.
* das ist das Signal,
dass dieses BO nicht von einem anderen BO referenziert wird. *///
return false;
}
Zusätzlicher
Code in der EJB-Klasse (bei Client/Server Anwendungen)
Wenn das
Anwendungsprogramm als Client/Server Programm, das den
EJB-Mechanismus verwendet, konzipiert ist, dann ist es notwendig, den
Aufruf jeder einzelnen Methode dieser Klasse auch in der Klasse und
den Interfaces für das EJB aufzunehmen.
Die Anleitung
dazu finden Sie unter
Muster-Codes
für die Klasse eines EJB (Enterprise Java Bean) mit
Datenbankzugriff > Methoden für die Datenzugriffe adaptieren
- generell
.
Spezieller
Muster-Code
In diesem Teil
wird Muster-Code vorgestellt, der nicht in jeder Server-seitigen
Klasse eines BO vorkommen wird und deswegen nicht in den Muster-Code
der Klasse aufgenommen wurde.
Prüfen
auf Konsistenz der Werte dieses BO
Im
Muster-Code ist die Methode
public boolean
isConsitentData()
enthalten
- aber kein Algorithmus für eventuelle Prüfungen
enthalten.
Prüfregeln müssen auf die jeweilige Aufgabe
des BO abgestimmt sein, ein Algorithmus-Schema würde den
verschiedenartigen Aufgaben nicht gerecht und deswegen wird auf einen
Beispiel-Algorithmus verzichtet.
Lesen von
Attributswerten von anderen Datenbank-Tabellen
- Methode
merge
Variablexy
Ein
Vorteil der Verwendung von Business-Objects (BO) ist, dass BOs mehr
Information enthalten können als ein Datensatz einer
DB-Tabelle.
Ein Beispiel dafür ist, dass die Variablen eines
BO aus den Werten von Attributen aus verschiedenen Datenbank-Tabellen
versorgt werden können.
Das erlaubt, z.B. Werte in 'Klartext'
in Variablen des BO verfügbar zu haben die auf der
haupt-zugeordneten Datenbank-Tabelle nur als ObjectID zu dem
referenzierten Datensatz einer anderen DB-Tabelle verfügbar
sind.
Im folgenden Muster-Code wird gezeigt, wie die gewünschten
Werte aus einer referenzierten Datenbank-Tabelle gelesen werden
können.
/* ---------------------
* METHODE zum 'Mischen' von Variablen-Werten aus einer
weiteren Datenbank-Tabelle. */
public
void
merge
Variablexy
() {
/*
* Ein BOS konstruieren über das dann das zu
'mischende' BO selektiert wird.
* Vorteil der Verwendung
eines BOS gegenüber einem DBA ist, dass bei einem BOS
*
auch eventuell weitere referenzierte Variablen-Werte mit der
Selektion 'geliefert'
* werden.
* Über den
boolschen Parameter 'true' wird signalisiert, dass die DB-Connection
* im konstruierten BOS nicht geschlossen werden darf. */
referenced_app_entity
_BOS
struct
referenced_app_entity
_BOS
=
new
referenced_app_entity
_BOS(
structJSBS_MinimalParameters
,
structDBCon
,
true
);
/*
*
Zu 'mischendes' BO von der Datenbank lesen. */
structreferenced_app_entity
_BOS.selectBy
SelectionCriteria
(
this
.
Referencing_Variable
);
/*
*
Einfaches Prüfen ob das referenzierte BO gefunden wurde. */
if
(struct
referenced_app_entity
_BOS.
StatusCode
==
JSBS_BO.
CONST_OK
)
{
/*
*
Gefunden: Referenzierte Werte auf dieses BO übertragen
*/
this
.
Referenced_Variable_1
= struct
referenced_app_entity
_BOS.
Referenced_Variable_1
;
this
.
Referenced_Variable_2
= struct
referenced_app_entity
_BOS.
Referenced_Variable_2
;
}
else
{
/*
*
Referenziertes BO wurde nicht gefunden. Individuell entscheiden wie
reagiert werden soll !!. */
}
}
Aufgerufen
wird diese Methode (
mergeVariable
xy
)
in den Methoden zum Selektieren bevor die Verbindung zur Datenbank
(Connection) beendet wird.
/*
* Über
die Länge des Textes mit einer eventuellen Fehler-Nachricht
prüfen ob
* die Datenbank-Abfrage fehlerfrei
beendet wurde.. */
if
(loc
application_dbtable
_DBA.
ErrorMsg
.length()
<= 1) {
/*
* Datensatz
existiert und wurde fehlerfrei gelesen.
* Attributs-Werte
auf die Variablen dieses BOS-Set übertragen.
*/
getDBAAttributes(locapplication_dbtable
_DBA_Set);
/*
Methode zum Übertrage von Variablen aus einem referenzierten BO
aufrufen. */
mergeVariablexy
();
/* Commit
ist nicht notwendig - aber in der aufgerufenen Methode wird
* wenn
notwendig die DB-Connection geschlossen.
* Anschließend
Methode beenden.
*/
commitDBConnection();
return
;
}
else
{
/* DBA-Objekt
meldet einen Fehler;
* Status-Code setzen und
Fehler-Meldung aus dem DBA-Objekt übernehmen.
*/
StatusCode
=
JSBS_BO.
CONST_DB_SYSTEM_ERROR
;
Dokument |
Inhalt |
Schritt desTutorials für die Entwicklung von Heavyweight-Client Anwendungen in dem die Implementierung der Server-Side Klasse für das BO vorgestellt wird. |
|
Muster-Code für ein BOS_Set (Liste mit Business-Objects, Server-Side-Klasse) |
Muster-Code für
die BOS-Klasse, mit denen eine Liste von Datensätzen
selektiert werden kann. |