Kein Folientitel

Werbung
Einsatz des ODS 5 API
im Projekt „Dämpferprüfstand“
bei der Audi AG
Erfahrungsbericht
1.
2.
3.
4.
5.
Aufgabenstellung
Performantes Lesen von Daten mit DB Views
IstecODS: Effiziente Entwicklung mit Hilfsklassen
Datenkonsistenz mit Hilfe von DB Triggern
Ausblick
© 06/2005
Aufgabenstellung
„Es ist ein Software-System zu entwickeln, welches die
effiziente Abwicklung, Datenhaltung und Auswertung von
verschiedenartigen Dämpferprüfungen ermöglicht.“
Einsatz von:
• ZEUS (Audi Komponenten Container)
• ASAM ODS mit ODS 5 API
• Oracle 9i
• DIAdem (X-Frame)
© 06/2005
Aufgabenstellung
Aufgaben:
• Verwalten und Suchen von:
• Aufträgen und Versuchen
• Fahrzeugen für Dauerlaufprüfungen
• Prüflingstypen und Prüflingen
• Kennlinien
• Generieren der Messprogramme für den Prüfstand
• Ergebnisablage in ODS
• Auswertung mit DIAdem
© 06/2005
ODS-Modell
© 06/2005
Komplexe Recherche und Ablage
© 06/2005
Performantes Lesen von Daten mit DB Views
Aufgabe:
Suchen von Aufträgen
Problem:
Information ist über 15 Applikationselemente verteilt. Die Suche
ist sehr zeitaufwendig. Das Auflösen von Relationen und das
Auslesen von Attributen bedeuten viele CORBA Roundtrips.
Lösung:
Verwendung von Datenbank-Views, via SQL-Joins. Im
Applikationsmodell werden Views z.B. als AoAny Tabellen
bekannt gemacht.
© 06/2005
Performantes Lesen von Daten mit DB Views
Vorteile:
• Konform zu ODS, da nur zusätzliche Tabellen definiert
werden müssen
• Ermöglicht Angabe von Suchkriterien über alle Attribute
• Instanzieren von vielen Java Objekten mit nur einer Abfrage
Nachteile:
• Pflege des Datenmodells ist aufwendiger
• Nutzung durch generische Applikationen ist nur bedingt möglich
© 06/2005
IstecODS: Effiziente Entwicklung mit Hilfsklassen
ODS Abfrage ohne Hilfsklasse:
QueryStructure query = new QueryStructure();
ApplicationElement ae = getViewApplicationElement();
(Fortsetzung)
ApplicationAttribute[] appAttrArr = ae.getAttributes("*");
ApplicationElement[] aeRelated = ae.getAllRelatedElements();
query.anuSeq = aidNUID;
AIDNameUnitId[] aidNUID = new AIDNameUnitId[appAttrArr.length +
aeRelated.length];
TS_Union value = new TS_Union();
value.longVal(pAuftragId);
int index = 0;
for (int i = 0; i < appAttrArr.length; ++i)
{
ApplicationAttribute appAttr = appAttrArr[i];
String attrName = appAttr.getName();
SelValue selVal = new SelValue();
aidNUID[index] = new AIDNameUnitId();
aidNUID[index].attr = new AIDName();
aidNUID[index].attr.aid = ae.getId();
aidNUID[index].attr.aaName = attrName;
aidNUID[index].unitId = new T_LONGLONG();
++index;
}
ApplicationStructure as = ae.getApplicationStructure();
for (int i = 0; i < aeRelated.length; ++i)
{
ApplicationRelation rel[] = as.getRelations(ae, aeRelated[i]);
// Expect there is only one relation
String relAttrName = null;
if ((rel != null) && (rel.length > 0))
{
RelationRange relRange = rel[0].getRelationRange();
// Only n:1 relations.
if (relRange.max == 1)
relAttrName = rel[0].getRelationName();
}
selVal.attr = new AIDNameValueUnitId ();
selVal.attr.unitId = new T_LONGLONG();
selVal.attr.values = new TS_Value();
selVal.attr.values.u = new TS_Union();
selVal.attr.values.u.stringVal("");
selVal.attr.attr = new AIDName();
selVal.attr.attr.aid = ae.getId();
selVal.attr.attr.aaName = AUFTRAG_ID;
selVal.value = new TS_Value();
selVal.value.u = value;
selVal.oper = SelOpcode.EQ;
query.condSeq = new SelValue[1];
query.condSeq[0] = selVal;
query.operSeq = new SelOperator[0];
query.orderBy = new SelOrder[1];
query.orderBy[0] = new SelOrder(new AIDName(ae.getId(), AUFTRAG_ID), true);
query.relInst = new org.asam.ods.ElemId();
query.relInst.aid = new T_LONGLONG();
query.relInst.iid = new T_LONGLONG();
query.relName = "";
ElemResultSet[] rs = as.getSession().getApplElemAccess().getInstances(query, 0);
aidNUID[index] = new AIDNameUnitId();
aidNUID[index].attr = new AIDName();
aidNUID[index].attr.aid = ae.getId();
aidNUID[index].attr.aaName = relAttrName;
aidNUID[index].unitId = new T_LONGLONG();
++index;
}
© 06/2005
IstecODS: Effiziente Entwicklung mit Hilfsklassen
ODS Abfrage mit Hilfsklasse:
QueryStructureGenerator qsg = new QueryStructureGeneratorImpl();
qsg.setAttributesToFetch(getViewApplicationElement()); // SQL: ‚select * …‘
TS_Union value = new TS_Union();
value.longVal(auftragId);
qsg.addCondition(getViewAID(), AUFTRAG_ID, value, SelOpcode.EQ); // SQL: ‚where ..‘
qsg.addOrderBy(getViewAID(), AUFTRAG_ID, true);
ODSResultSet rs = qsg.executeQuery(getApplElemAccess());
Vorteile:
• Korrekte und vollständige Befüllung von
org.asam.ods.QueryStructure Instanzen
• Verständlicher und überschaubarer Quellcode
• Transparente Cache Nutzung
© 06/2005
IstecODS: Effiziente Entwicklung mit Hilfsklassen
ODS Ergebnisauswertung ohne Hilfsklasse:
ElemResultSet[] rs = as.getSession().getApplElemAccess().getInstances(query, 0);
System.out.println("ResultSet size = " + rs.length);
for (int i = 0; i < rs.length; ++i)
{
for (int k = 0; k < rs[i].attrValues.length; ++k)
{
NameValueSeqUnitId nvsuid = rs[i].attrValues[k].attrValues;
System.out.println("ValueName (" + i + ":" + k + "): " + nvsuid.valName);
switch (nvsuid.value.u.discriminator().value())
{
case DataType._DT_STRING:
String[] valuesString = nvsuid.value.u.stringVal();
for (int m = 0; m < valuesString.length; ++m)
System.out.println("Value (" + m + "): " + valuesString[m]);
break;
case DataType._DT_LONG:
int[] valuesInt = nvsuid.value.u.longVal();
for (int m = 0; m < valuesInt.length; ++m)
System.out.println("Value (" + m + "): " + valuesInt[m]);
break;
case DataType._DT_BOOLEAN:
int[] valuesBoolean = nvsuid.value.u.longVal();
for (int m = 0; m < valuesBoolean.length; ++m)
System.out.println("Value (" + m + "): " + valuesBoolean[m]);
break;
/*
* ...
* ...
*/
default:
break;
}
}
}
© 06/2005
IstecODS: Effiziente Entwicklung mit Hilfsklassen
ODS Ergebnisauswertung mit Hilfsklasse:
ODSResultSet rs = qsg.executeQuery(getApplElemAccess());
while (rs.next())
{
Integer auftragid = rs.getInteger("AUFTRAG_ID");
String kommentar = rs.getString("AUFTRAG_KOMMENTAR");
Boolean dauerlauf = rs.getBoolean("AUFTRAGDAUERLAUFKZ");
/*
* ...
* ...
*/
}
Vorteile:
• Zeilenorientierte Verarbeitung der spaltenorientierten QueryErgebnismenge org.asam.ods.ElemResultSet[]
• Automatische Typkonvertierung
• Verständlicher und überschaubarer Quellcode
© 06/2005
Datenkonsistenz mit Hilfe von DB Triggern
Aufgabe:
Datenkonsistenz gewährleisten bei konkurrierenden
Datenzugriffen von mehreren ODS-Clients auf einem
ODS-Server.
Lösung:
Via Datenbank-Trigger wird ein Attribut ‚Version‘ zur
Datensatzversionierung erhöht.
Dieses Attribut ist in der SVCATTR als ‚AUTOGENERATE‘
markiert.
Zwischenzeitliche Änderungen am Datensatz durch einen
anderen ODS-Client sind durch Prüfen der Versionsnummer
auf Gleichheit feststellbar.
© 06/2005
Datenkonsistenz mit Hilfe von DB Triggern
Beispiel für einen Trigger:
CREATE OR REPLACE TRIGGER tau_tblauftrag before update or insert on tblauftrag for each row
begin
if inserting then
:NEW.sysanleger := RTRIM(USER);
:NEW.version := '1';
:NEW.odsname := 'AUFTRAG-' || TO_CHAR(:NEW.auftragid);
else
:NEW.version := TO_CHAR(TO_NUMBER(:OLD.version) + 1);
end if;
:NEW.aendererdz := SYSDATE;
:NEW.sysaenderer := RTRIM(USER);
end;
© 06/2005
Ausblick
• Umsetzung der in ODS 5 spezifizierten ‚Extended Query Structure‘
(org.asam.ods.QueryStructureExt) sollte den Einsatz von DatenbankViews weitgehend unnötig machen.
• Derzeit ist das Lesen von Blobs nur über Instanzelemente möglich.
Einstellen von DT_Blobs in das org.asam.ods.ElemResultSet[] wenn
angefordert erspart Roundtrips.
© 06/2005
Danke für die Aufmerksamkeit.
© 06/2005
Herunterladen