© 06/2005
Einsatz des ODS 5 APIim Projekt „Dämpferprüfstand“
bei der Audi AG
Erfahrungsbericht
1. Aufgabenstellung2. Performantes Lesen von Daten mit DB Views3. IstecODS: Effiziente Entwicklung mit Hilfsklassen4. Datenkonsistenz mit Hilfe von DB Triggern5. 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
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
Aufgabenstellung
© 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(); ApplicationAttribute[] appAttrArr = ae.getAttributes("*"); ApplicationElement[] aeRelated = ae.getAllRelatedElements(); AIDNameUnitId[] aidNUID = new AIDNameUnitId[appAttrArr.length + aeRelated.length]; int index = 0; for (int i = 0; i < appAttrArr.length; ++i) { ApplicationAttribute appAttr = appAttrArr[i]; String attrName = appAttr.getName(); 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(); } 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; }
(Fortsetzung)
query.anuSeq = aidNUID; TS_Union value = new TS_Union(); value.longVal(pAuftragId); SelValue selVal = new SelValue();
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);
© 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 Query- Ergebnismenge 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‘ zurDatensatzversionierung erhöht.
Dieses Attribut ist in der SVCATTR als ‚AUTOGENERATE‘ markiert.
Zwischenzeitliche Änderungen am Datensatz durch einenanderen 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 rowbegin 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 Datenbank- Views 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.
Top Related