Informatik Zusammenfassung JII.2 #1

Werbung
Informatik Zusammenfassung JII.2 #1
Entity-Relationship-Modell erstellen
Aufgabenstellung
Eine Firma möchte ihre Abteilungen über eine Datenbank verwalten. Hierbei soll jeder Abteilung ein
Name und ein Zimmer zugeteilt werden. Weiterhin hat jede Abteilung einen Abteilungsleiter, der mit
Name und Anschrift erfasst werden soll. Zudem soll jeder Abteilung Material mit den Attributen
Bezeichnung, Vorrat und Kosten zugeteilt werden. Erstelle ein Entity-Relationship-Modell.
Beispiel: Die Personalabteilung hat den Abteilungsleiter Peter Mayer und hat die Materialien
Computer, Kugelschreiber und Papier.
Lösung
1. Schritt: Entitätstypen und Beziehungen (+ Kardinalitäten) identifizieren
Entitätstypen sind in Datenbanken das was man früher unter einer Klasse verstand. So war der Kunde
früher ein Entitätstyp. Das was wir früher als Objekt einer Klasse bezeichnet haben heißt bei
Datenbanken Entität eines Entitätstyps. Kardinalitäten bestimmen die Mengenverbindungen
zwischen den einzelnen Tabellen (Bsp.: Ein Ort kann mehrere Einwohner haben, aber ein Einwohner
lässt sich eindeutig zu einem Ort zuordnen – Also ist die Kardinalität 1:n). Es kann allerdings keine
n:m Verbindung geben!
Entitäten:
Abteilung
Abteilungsleiter
Material
Karsdinalitäten:
Abteilung
1:1
Abteilung
1:n
Abteilungsleiter
Material
2. Schritt: Identitätsschlüssel (Primärschlüssel) und Fremdschlüssel für Entitäten
bestimmen
Ein Primärschlüssel identifiziert ein Objekt eindeutig (z.B. gibt es nur eine PLZ für jeden Ort; es gibt
keine zwei Orte mit gleicher PLZ – ein Name hingegen ist nicht geeignet als Primärschlüssel zu
fungieren, da es mehrere verschiedene Personen mit dem gleichen Namen geben kann). Falls sich
kein Primärschlüssel aus der Aufgabenstellung identifizieren lässt, so erstellt man sich einen eigenen:
Üblich ist eine laufende Nummer. Über den Primärschlüssel findet man das jeweilige Objekt in der
Datenbank
Um Verbindungen zwischen den einzelnen Tabellen in der Datenbank herzustellen werden
Fremdschlüssel vergeben. Diese Fremdschlüssel sind die Primärschlüssel der jeweils verbunden
Entitätstypen. Ist einer Abteilung bspw. die LeiterNr „1“ zugeteilt, so ist der Leiter mit der LeiterNr
„1“ in der Tabelle Abteilungsleiter die Führungskraft in der Abteilung.
Seite 1
Primärschlüssel:
Abteilung: AbteilungsNr
Abteilungsleiter: LeiterNr
Material: MaterialNr
Fremdschlüssel:
Abteilung: LeiterNr
Abteilung: MaterialNr
3. Schritt: Attribute und ihre Wertebereiche der Entitätstypen bestimmen
Man muss wie beim normalen Programmieren den Attributen eine „Form“ vorgeben. Diese Formen
sind die Datentypen. Bei Datenbanken sind die folgenden Formen wichtig: CHAR(), VARCHAR(%n)
BOOLEAN, DATE, DATETIME, DOUBLE, FLOAT, INT. In den Klammern hinter CHAR lässt sich eine
maximale Länge der Zeichenkette eingeben, VARCHAR dagegen erweitert sich selbst falls die Länge
zu kurz ist.
Abteilung:
- Name: VARCHAR()
-Zimmer: VARCHAR()
-LeiterNr: CHAR(10)
-MaterialNr: CHAR(10)
Abteilungsleiter:
-LeiterNr: CHAR(10)
-Name: VARCHAR()
-Anschrift: VARCHAR()
Material:
-MaterialNr: CHAR(10)
-Bezeichnung: VARCHAR()
-Vorrat: INT
-Kosten: DOUBLE
4. Schritt: Schema erstellen
All diese Informationen stellt man
abschließend in einem Schema da, in dem
die Entitätstypen durch Pfeile verbunden
werden die bspw. durch Pfeile (bei uns
durch Rauten). Die Kardinalitäten werden
jeweils an die Pfeilenden geschrieben.
Datenbank in Eclipse eingeben
Um ein solches Modell in Eclipse zu übertragen muss man
zunächst eine neue *.clay-Datei erstellen. Dies erreicht man mit
rechtsklick auf das Projekt. Dort findet sich unter „New“ ganz
unten der Punkt „Other“. Nach klick hierauf öffnet sich ein
Seite 2
weiteres Fenster. In diesem findet sich im Ordner „Database Modelling“ der Eintrag „Clay Database
Design Diagram“. Dieser wird ausgewählt! Anschließend kommt ein weiteres Fenster in dem nur
noch der Dateiname eingegeben werden muss und dass dann auch mit „Fertig stellen“ geschlossen
werden kann.
Nun sollte sich ein blaugraues Fenster geöffnet haben mit einer kleinen Symbolleiste an
der linken Seite, die etwa wie diese hier aussehen sollte. Zunächst benutzen wir das
unterste Tool – hiermit können wir die Entitätstypen erstellen. Ist das Tool ausgewählt
wird einmal in die Arbeitsfläche geklickt und eine leere Tabelle erscheint. Auf diese wird
doppelt geklickt, sodass sich ein Fenster öffnet. Dieses Fenster hat die Registerkarten
„Table“ und die „Columns“. In der Registerkarte „Table“ wird zunächst unter „Name:“
der Name der Entität eingetragen (bspw.: Abteilung) – die anderen Felder kann man
sich schenken.
Nun zur Registerkarte „Columns“. Hier fügen wir zunächst mittels „Add new“ ein neues Attribut
hinzu. Bei „Name:“ wird der jeweilige Name eingegeben, bei „Data Type“ der entsprechende
Datentyp ausgewählt. Interessant sind noch die Checkboxen unten im Fenster. Beim Primärschlüssel
muss die Checkbox „Primary Key“ gewählt sein! „Mandatory“ steht für Pflichtfelder die nicht leer
sein dürfen (wird üblicherweise auch gewählt, ist aber nicht so wichtig in unserem Fall) und „Auto
Increment“ steht eigentlich für laufende Nummern, funktioniert allerdings bei uns nicht!
Die fertige Tabelle für den Abteilungsleiter sollte etwa so aussehen:
Mit Klick auf „OK“ werden die Daten in die Tabelle übernommen, sie ist fertig. Genauso verfahren wir
nun noch mit Material und Abteilungsleiter, sodass wir drei Tabellen im Arbeitsfenster haben. Nun
bedienen wir uns des zweituntersten Symbols der Symbolleiste. Mit diesem Symbol (
) können wir
die einzelnen Entitätstypen miteinander in Beziehungen setzen. Dazu klickt man zunächst auf die
übergeordnete Tabelle (also bspw.: Abteilung) und anschließend auf die untergeordnete Tabelle
(bspw.: Material). Die beiden Tabellen sind dann durch eine Linie verbunden und in der oberen
Tabelle taucht nun auch der Fremdschlüssel der unteren Tabelle auf.
Will man den Verbindungen noch Kardinalitäten zuweisen,
so muss doppelt auf die Verbindung geklickt werden und im
sich öffnenden Fenster kann in der Registerkarte
„Decorations“ der jeweilige Typ ausgewählt werden. An
einem Ende steht jeweils wie viele Entitäten es von diesem
Entitätstyp geben kann. An der Abteilung wird also jeweils
eine „1“ stehen, da es nur eine Abteilung pro Leiter und
Material gibt, ebenso am Abteilungsleiter. Am Material steht
„0…*“ da es pro Abteilung kein bis unendlich viel Material
geben kann. Fertig sieht das Diagramm nun so aus wie hier rechts.
Seite 3
bIst das Diagramm fertig,
so muss man es in einen
SQL-Code übersetzen (SQL
ist die Programmiersprache für Datenbanken). Dazu klickt man irgendwo in den Arbeitsbereich mit
der rechten Maustaste und wählt „Generate SQL (CREATE TABLE) Script…“ (s. Bild). Im sich öffnenden
Fenster gibt man dem Script noch einen Namen und bestätigt mit „Fertig stellen“.
Anschließend öffnet sich das fertige Script.
Daneben öffnet sich zusätzlich noch die
„Connection“-Registerkarte. In dieser müssen wir
eine neue Verbindung zur Datenbank herstellen (diese Verbindung benutzt dann später die Klasse
DBZugriff). Dazu wählen wir den ersten Punkt der Symbolleiste aus welcher hier im Bild auch
angewählt ist. Dann öffnet sich wiederum ein Fenster in welchem man dann den Namen der
Verbindung eingeben muss, bei Driver den „MySQL Driver“ wählen muss und bei User den Namen
„root“ eintragen muss. Weiterhin müssen noch die Hacken vor „Auto Logon“ und „Auto Commit“
gesetzt werden. Nach Bestätigen mit „OK“ ist die Verbindung hergestellt – sie erscheint auch nun im
„Connections“-Fenster. Klickt man doppelt auf sie öffnet sich ein weiteres Fenster in dem kurz
geladen wird, wir aktivieren dadurch nämlich die Verbindung. Anschließend steht hinter dem
Verbindungsname in Klammern eine Anzahl an laufenden Verbindungen (mindestens 1). Das ist das
Zeichen das alles funktioniert hat. Des Weiteren hat sich ein leeres Textfenster geöffnet. In diesem
Fenster wird nun zunächst eine neue Datenbank erstellt. Dies geschieht mittels Eingabe des Befehls
„CREATE DATABASE …“. Statt … wird der jeweilige Name eingegeben (in unserem Fall Firma).
Anschließend wird der ganze Code aus der vorhin erstellten SQL-Datei dahinter kopiert. Falls
irgendwo das Wort „DEFAULT_SCHEMA“ auftaucht muss es übrigens ebenfalls durch den Namen der
Datenbank ersetzt werden (passiert evtl. bei euch zuhause beim üben – in der Schule wohl eher
nicht).
Diesen Ganzen Code kann man nun mit Klick auf dieses Symbol
ausführen lassen. Wenn keine
Fehlermeldungen kommen hat es geklappt. Überprüfen kann man das noch mit dem Befehl „SELECT
* FROM …“, wobei man … durch den Tabellennamen ersetzt. Bekommt man keinen Fehler hat es
wiederum funktioniert.
Arbeiten mit Datenbanken (speichern, lesen, ändern, löschen)
4-Schichten-Architektur
Das GUI (Graphical-User-Interface) stellt die Verbindungsschicht zwischen dem Benutzer und dem
Programm dar. In diesem kann der Nutzer seine Befehle ausführen und Daten eingeben.
Wünscht der Nutzer ein Befehl in der Datenbank auszuführen, dann dürchläuft dieser Befehl alle vier
Schichten:
Zunächst wird in der GUI-Schicht ein Objekt der Fachklasse erstellt, welches wiederrum eine
Methode X aus der Fachklasse ausführt. Diese Methode X ist in der Fachklasse Programmiert und
erstellt wiederrum ein Objekt der Verbindungsschicht, welches wiederrum eine Methode Y aus der
Verbindungsschicht ausführen kann. Diese Methode Y ändert, löscht oder fügt Daten zu der
Datenbank hinzu.
GUI
Fachklasse
Verbindungsschicht
Seite 4
Datenbank
Generelles Vorgehen
Zunächst einmal muss auf jeden Fall eine oder mehrere Fachklasse (get-/set-Methoden, Attribute)
sowie die Visual-Class programmiert werden. In dem Hauptfenster muss mittels der folgenden Zeile
noch ein Objekt der Fachklasse angelegt werden:
private Abteilungsleiter leiter1 = null;
Weiterhin brauchen wir eine Methode, die die Daten von den Textfeldern in das Objekt überträgt.
Dazu erstellen wir den Button „btAnlegen“ der ein Action-Performed-Event erhält welches wiederum
die Methode anlegen ausführt die wie folgt programmiert wird (bis hier noch Stoff der letzten
Klausuren!)
private void anlegen()
{
leiter1 = new Abteilungsleiter(tfNummer.getText());
leiter1.setName(tfName.getText());
leiter1.setAnschrift(tfAnschrift.getText());
}
Speichern, ändern, löschen
Diese drei Vorgehensweisen sind alle nahezu ähnlich, von daher lassen sie sich relativ gut zusammen
erläutern. In jedem der drei Fälle brauchen wir einen Button mit Action-Performed-Event der dann
die jeweilige Methode in der Fachklasse ausführt die wir programmieren müssen. Wir müssen daher
auf das vorher erstellte Objekt zugreifen. Bei ändern beispielsweise braucht die Methode noch einen
Übergabewert, damit die Methoe weiß, welcher Abteilungsleiter geändert werden soll. Dazu bietet
sich der „InputDialog“ beim JOptionPane an!
//Abfragen der Kundennummer nach der gesucht werden soll. Speichern der
Nummer im String s
String s = JOptionPane.showInputDialog(null, "Bei welcher Nummer soll
geändert werden?");
leiter1.aendern(s);
//ActionListener der die Methode aendern() des Abteilungsleiterobjektes
ausführt
Jede der Methoden läuft gleich ab: Datenbank öffnen, SQL-Befehl schreiben, SQL-Befehl an die
Verbindungsschicht übergeben und Datenbank schließen. Die SQL-Befehle sind jeweils anders aber
die könnt ihr aus Frau Dercks Formelsammlung holen.
public void erfasse() {
//Objekt der Verbindungsschicht erstellen
DBZugriff aktuellerZugriff = new DBZugriff();
//Datenbank öffnen
aktuellerZugriff.oeffneDB();
//SQL-Befehl erstellen und im String stmt speichern
String stmt = "INSERT INTO abteilungsleiter (LeiterNr ,Name
,Anschrift)"
+ "VALUES ('" + leiterNr + "', '" + name + "', '" + anschrift + ');";
//SQL-Befehl ausführen
aktuellerZugriff.aendern(stmt);
//Datenbank schließen
aktuellerZugriff.schliesseDB();
}
public void aendern(String primKey) { //String primKey ist die LeiterNr des
Kunden der geändert werden soll!
Seite 5
DBZugriff aktuellerZugriff = new DBZugriff();
aktuellerZugriff.oeffneDB();
String stmt = "UPDATE abteilungsleiter SET LeiterNr = '"+leiterNr+"',
Name = '"+name+"',"
+ "Anschrift = '"+anschrift+"' WHERE LeiterNr = '"+primKey+"';";
aktuellerZugriff.aendern(stmt);
aktuellerZugriff.schliesseDB();
}
public void delete() {
DBZugriff aktuellerZugriff = new DBZugriff();
aktuellerZugriff.oeffneDB();
String stmt = "DELETE FROM abteilungsleiter WHERE LeiterNr =
'"+leiterNr+"';";
aktuellerZugriff.aendern(stmt);
aktuellerZugriff.schliesseDB();
}
Suchen
Vom Grundaufbau ist auch die Suchen-Methode ähnlich den drei anderen. Allerdings erhalten wir
hier einen Rückgabewert der auch ausgewertet werden muss. Zunächst aber fragen wir (wie beim
ändern) ab nach welcher LeiterNr gesucht werden soll (InputDialog!) und leiten die weiter an die
Methode suchen() in der Fachklasse die dann programmiert wird.
In der Methode suchen() wird die Datenbank auch zunächst geöffnet und der SQL-Befehl wird
übergeben und ausgeführt. Dieses Mal verwenden wir allerdings statt
aktuellerZugriff.aendern nun aktuellerZugriff.lesen und wir müssen den
Rückgabewert dieser Methode in einem Resultset abspeichern der dann mittels return
zurückgegeben wird.
public ResultSet suchen(String primKey) //String primKey ist die LeiterNr
des Kundne der geändert werden soll!
{
DBZugriff aktuellerZugriff = new DBZugriff();
aktuellerZugriff.oeffneDB();
String stmt = "SELECT * FROM abteilungsleiter WHERE LeiterNr LIKE
'"+primKey+"'";
//Methode lesen statt aendern verwenden und den Rückgabewert im
Resultset speichern
ResultSet rs = aktuellerZugriff.lesen(stmt);
aktuellerZugriff.schliesseDB();
//das Resultset an das Hauptfenster zurückgeben - dort wird es
ausgewertet
return rs;
}
Das Resultset wird dann von der ursprünglichen Methode ausgewertet. Zunächst wird die next()Methode aufgerufen die das nächste Objekt des ResultSets (also das was wir gesucht haben)
zurückgibt. Anschließend erhält man über getString(„Attributsname“) den Wert des jeweiligen
Attributs, der dann ins Textfeld übertragen wird. Der try-catch-Block ist hier übrigens Pflicht!
//Abfragen der Kundennummer nach der gesucht werden soll. Speichern der
Nummer im String s
String s = JOptionPane.showInputDialog(null, "Nach welcher Nummer soll
gesucht werden?");
ResultSet rs = leiter1.suchen(s); //ActionListener der die Methode suchen()
des Abteilungsleiterobjektes ausführt und speichern im ResultSet
Seite 6
try {
rs.next(); //Standartzeile - einfach auswendig lernen
//Übertragen der jeweiligen Daten aus dem Resultset
tfNummer.setText(rs.getString("LeiterNr"));
tfName.setText(rs.getString("Name"));
tfAnschrift.setText(rs.getString("Anschrift"));
//Fehlerbehandlung
} catch (SQLException ex) {
ex.printStackTrace();
}
Fehlerbehandlung
Beim Arbeiten mit Datenbanken können an verschiedenen Stellen Fehler auftreten, die man
abfangen sollte. Dabei arbeitet man mit mehreren try-catch Blöcken. Weiterhin muss man beachten,
dass eine Datenbank bei der das öffnen nicht geklappt hat nicht bearbeitet werden kann.
public void aendern(String primKey)
{
DBZugriff aktuellerZugriff = new DBZugriff();
int mOK=0;
if(aktuellerZugriff.oeffneDB()==true)
{
mOK=1;
String stmt = "UPDATE abteilungsleiter SET LeiterNr =
'"+leiterNr+"', Name = '"+name+"',"
+ "Anschrift = '"+anschrift+"' WHERE LeiterNr =
'"+primKey+"';";
if(aktuellerZugriff.aendern(stmt)==true)
{
mOK=2;
if(aktuellerZugriff.schliesseDB()==true)
{
mOK=3;
}
}
}
switch(mOK)
{
case 0: JOptionPane.showMessageDialog(null, "Das Öffnen der
Datenbank ist fehlgeschlagen!");
break;
case 1: JOptionPane.showMessageDialog(null, "Das Ändern der
Datenbank ist fehlgeschlagen!");
break;
case 2: JOptionPane.showMessageDialog(null, "Das Schließen der
Datenbank ist fehlgeschlagen!");
break;
case 3: JOptionPane.showMessageDialog(null, "Es hatt alles
funktioniert!");
break;
}
}
Seite 7
Zunächst einmal muss man einen Integer einfügen (In diesem Fall mOK), der je nach Fehlerquelle
später einen anderen Wert einnehmen wird. Zunächst wird er als Null definiert.
Darüber hinaus muss man wissen, dass die Methoden aus der Verbindungsschicht jeweils einen
Boolean als Rückgabewert besitzen, der angibt, ob die Methode funktioniert hat (true wenn sie
funktioniert hat und false wenn nicht). Daher setzt man die Methode in einen if-Block der den
Rückgabewert überprüft. Falls das Öffnen nicht geklappt hat, bleibt mOK null und die Datenbank wird
nicht weiter bearbeitet (verzweigte if Bedingungen beachten!). Falls das Öffnen geklappt hat, dann
wird mOK 1 und es wird zunächst versucht die Datenbank zu ändern und danach zu schließen.
Je nachdem wird mOK dann zwei, wenn die Datenbank erfolgreich geändert wurde und 3 wenn sie
auch erfolgreich geschlossen werden konnte.
Nun muss der Wert von mOK ausgewertet werden. Dies wird am einfachsten mit einem Switch-caseBlock gelöst. In der Switch-Anweisung steht mOk in der Klammer und es wird je nach Wert der
entsprechende Case-Block ausgeführt. Falls mOK = 0 ist schon das Öffnen gescheitert, bei mOK=1 ist
das Ändern fehlgeschlagen und bei mOK=2 führte das Schlie0en zu einem Fehler. Besitzt mOK den
Wert 3 dann hat alles perfekt funktioniert.
Im Jeweiligen Case-Block wird die passende Meldung ausgegeben. Jeder Case-Block muss mit einem
break-Befehl enden, damit der Compiler nicht fälschlicherweise auch die anderen Case-Blöcke
ausführt.
Suchen:
try {
rs.next(); //Standartzeile - einfach auswendig lernen
//Übertragen der jeweiligen Daten aus dem Resultset
tfNummer.setText(rs.getString("LeiterNr"));
tfName.setText(rs.getString("Name"));
tfAnschrift.setText(rs.getString("Anschrift"));
//Fehlerbehandlung
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(null, "Es wurde nichts gefunden!");
}
Die suchen-Methode kann auch noch abstürzen, wenn kein Eintrag in der Datenbank gefunden
wurde. Deshalb muss man in den schon bestehenden Catch-Block noch die Fehlermeldung
programmieren.
Fertig ist die Info-Zusammenfassung für die Klausur am nächsten Montag. Sie hat ja
halbwegs deutlich gesagt wie die Aufgaben aussehen sollten und in etwa die Teile ist auch
die Zusammenfassung jetzt auch aufgeteilt.
Wie immer bei Fehlern/Fragen/eigenen Zusammenfassungen/… könnt ihr mir eine Mail
schreiben ([email protected]). Ansonsten viel Erfolg am Montag. Ein Dankeschön geht noch an
Kai Salzmann für die Hilfe bei der Zusammenfassung.
Gruß,
Florian
Seite 8
Herunterladen