This commit is contained in:
Asecave
2021-10-24 17:17:34 +02:00
parent 8e8d1f0d99
commit bebc0f886e
3 changed files with 363 additions and 198 deletions

View File

@@ -8,141 +8,145 @@ import java.sql.*;
* Klasse DatabaseConnector * Klasse DatabaseConnector
* </p> * </p>
* <p> * <p>
* Ein Objekt der Klasse DatabaseConnector ermoeglicht die Abfrage und Manipulation * Ein Objekt der Klasse DatabaseConnector ermoeglicht die Abfrage und
* einer SQLite-Datenbank. * Manipulation einer SQLite-Datenbank. Beim Erzeugen des Objekts wird eine
* Beim Erzeugen des Objekts wird eine Datenbankverbindung aufgebaut, so dass * Datenbankverbindung aufgebaut, so dass anschließend SQL-Anweisungen an diese
* anschließend SQL-Anweisungen an diese Datenbank gerichtet werden koennen. * Datenbank gerichtet werden koennen.
* </p> * </p>
* *
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule * @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
* @version 2016-01-24 * @version 2016-01-24
*/ */
public class DatabaseConnector{ public class DatabaseConnector {
private Connection connection; private Connection connection;
private QueryResult currentQueryResult = null; private QueryResult currentQueryResult = null;
private String message = null; private String message = null;
/** /**
* Ein Objekt vom Typ DatabaseConnector wird erstellt, und eine Verbindung zur Datenbank * Ein Objekt vom Typ DatabaseConnector wird erstellt, und eine Verbindung zur
* wird aufgebaut. Mit den Parametern pIP und pPort werden die IP-Adresse und die * Datenbank wird aufgebaut. Mit den Parametern pIP und pPort werden die
* Port-Nummer uebergeben, unter denen die Datenbank mit Namen pDatabase zu erreichen ist. * IP-Adresse und die Port-Nummer uebergeben, unter denen die Datenbank mit
* Mit den Parametern pUsername und pPassword werden Benutzername und Passwort fuer die * Namen pDatabase zu erreichen ist. Mit den Parametern pUsername und pPassword
* Datenbank uebergeben. * werden Benutzername und Passwort fuer die Datenbank uebergeben.
*/ */
public DatabaseConnector(String pIP, int pPort, String pDatabase, String pUsername, String pPassword){ public DatabaseConnector(String pIP, int pPort, String pDatabase, String pUsername, String pPassword) {
//Eine Impementierung dieser Schnittstelle fuer SQLite ignoriert pID und pPort, da die Datenbank immer lokal ist. // Eine Impementierung dieser Schnittstelle fuer SQLite ignoriert pID und pPort,
//Auch pUsername und pPassword werden nicht verwendet, da SQLite sie nicht unterstuetzt. // da die Datenbank immer lokal ist.
try { // Auch pUsername und pPassword werden nicht verwendet, da SQLite sie nicht
//Laden der Treiberklasse // unterstuetzt.
Class.forName("org.sqlite.JDBC"); try {
// Laden der Treiberklasse
Class.forName("org.sqlite.JDBC");
//Verbindung herstellen // Verbindung herstellen
connection = DriverManager.getConnection("jdbc:sqlite:"+pDatabase); connection = DriverManager.getConnection("jdbc:sqlite:" + pDatabase);
} catch (Exception e) { } catch (Exception e) {
message = e.getMessage(); message = e.getMessage();
} }
} }
/** /**
* Der Auftrag schickt den im Parameter pSQLStatement enthaltenen SQL-Befehl an die * Der Auftrag schickt den im Parameter pSQLStatement enthaltenen SQL-Befehl an
* Datenbank ab. * die Datenbank ab. Handelt es sich bei pSQLStatement um einen SQL-Befehl, der
* Handelt es sich bei pSQLStatement um einen SQL-Befehl, der eine Ergebnismenge * eine Ergebnismenge liefert, so kann dieses Ergebnis anschließend mit der
* liefert, so kann dieses Ergebnis anschließend mit der Methode getCurrentQueryResult * Methode getCurrentQueryResult abgerufen werden.
* abgerufen werden. */
*/ public void executeStatement(String pSQLStatement) {
public void executeStatement(String pSQLStatement){ // Altes Ergebnis loeschen
//Altes Ergebnis loeschen currentQueryResult = null;
currentQueryResult = null; message = null;
message = null;
try { try {
//Neues Statement erstellen // Neues Statement erstellen
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
//SQL Anweisung an die DB schicken. // SQL Anweisung an die DB schicken.
if (statement.execute(pSQLStatement)) { //Fall 1: Es gibt ein Ergebnis if (statement.execute(pSQLStatement)) { // Fall 1: Es gibt ein Ergebnis
//Resultset auslesen // Resultset auslesen
ResultSet resultset = statement.getResultSet(); ResultSet resultset = statement.getResultSet();
//Spaltenanzahl ermitteln // Spaltenanzahl ermitteln
int columnCount = resultset.getMetaData().getColumnCount(); int columnCount = resultset.getMetaData().getColumnCount();
//Spaltennamen und Spaltentypen in Felder uebertragen // Spaltennamen und Spaltentypen in Felder uebertragen
String[] resultColumnNames = new String[columnCount]; String[] resultColumnNames = new String[columnCount];
String[] resultColumnTypes = new String[columnCount]; String[] resultColumnTypes = new String[columnCount];
for (int i = 0; i < columnCount; i++){ for (int i = 0; i < columnCount; i++) {
resultColumnNames[i] = resultset.getMetaData().getColumnLabel(i+1); resultColumnNames[i] = resultset.getMetaData().getColumnLabel(i + 1);
resultColumnTypes[i] = resultset.getMetaData().getColumnTypeName(i+1); resultColumnTypes[i] = resultset.getMetaData().getColumnTypeName(i + 1);
} }
//Queue fuer die Zeilen der Ergebnistabelle erstellen // Queue fuer die Zeilen der Ergebnistabelle erstellen
Queue<String[]> rows = new Queue<String[]>(); Queue<String[]> rows = new Queue<String[]>();
//Daten in Queue uebertragen und Zeilen zaehlen // Daten in Queue uebertragen und Zeilen zaehlen
int rowCount = 0; int rowCount = 0;
while (resultset.next()){ while (resultset.next()) {
String[] resultrow = new String[columnCount]; String[] resultrow = new String[columnCount];
for (int s = 0; s < columnCount; s++){ for (int s = 0; s < columnCount; s++) {
resultrow[s] = resultset.getString(s+1); resultrow[s] = resultset.getString(s + 1);
} }
rows.enqueue(resultrow); rows.enqueue(resultrow);
rowCount = rowCount + 1; rowCount = rowCount + 1;
} }
//Ergebnisfeld erstellen und Zeilen aus Queue uebertragen // Ergebnisfeld erstellen und Zeilen aus Queue uebertragen
String[][] resultData = new String[rowCount][columnCount]; String[][] resultData = new String[rowCount][columnCount];
int j = 0; int j = 0;
while (!rows.isEmpty()){ while (!rows.isEmpty()) {
resultData[j] = rows.front(); resultData[j] = rows.front();
rows.dequeue(); rows.dequeue();
j = j + 1; j = j + 1;
} }
//Statement schließen und Ergebnisobjekt erstellen // Statement schließen und Ergebnisobjekt erstellen
statement.close(); statement.close();
currentQueryResult = new QueryResult(resultData, resultColumnNames, resultColumnTypes); currentQueryResult = new QueryResult(resultData, resultColumnNames, resultColumnTypes);
} else { //Fall 2: Es gibt kein Ergebnis. } else { // Fall 2: Es gibt kein Ergebnis.
//Statement ohne Ergebnisobjekt schliessen // Statement ohne Ergebnisobjekt schliessen
statement.close(); statement.close();
} }
} catch (Exception e) { } catch (Exception e) {
//Fehlermeldung speichern // Fehlermeldung speichern
message = e.getMessage(); message = e.getMessage();
} }
} }
/** /**
* Die Anfrage liefert das Ergebnis des letzten mit der Methode executeStatement an * Die Anfrage liefert das Ergebnis des letzten mit der Methode executeStatement
* die Datenbank geschickten SQL-Befehls als Ob-jekt vom Typ QueryResult zurueck. * an die Datenbank geschickten SQL-Befehls als Ob-jekt vom Typ QueryResult
* Wurde bisher kein SQL-Befehl abgeschickt oder ergab der letzte Aufruf von * zurueck. Wurde bisher kein SQL-Befehl abgeschickt oder ergab der letzte
* executeStatement keine Ergebnismenge (z.B. bei einem INSERT-Befehl oder einem * Aufruf von executeStatement keine Ergebnismenge (z.B. bei einem INSERT-Befehl
* Syntaxfehler), so wird null geliefert. * oder einem Syntaxfehler), so wird null geliefert.
*/ */
public QueryResult getCurrentQueryResult(){ public QueryResult getCurrentQueryResult() {
return currentQueryResult; if (currentQueryResult == null) {
} System.out.println(getErrorMessage());
}
return currentQueryResult;
}
/** /**
* Die Anfrage liefert null oder eine Fehlermeldung, die sich jeweils auf die letzte zuvor ausgefuehrte * Die Anfrage liefert null oder eine Fehlermeldung, die sich jeweils auf die
* Datenbankoperation bezieht. * letzte zuvor ausgefuehrte Datenbankoperation bezieht.
*/ */
public String getErrorMessage(){ public String getErrorMessage() {
return message; return message;
} }
/** /**
* Die Datenbankverbindung wird geschlossen. * Die Datenbankverbindung wird geschlossen.
*/ */
public void close(){ public void close() {
try{ try {
connection.close(); connection.close();
} catch (Exception e) { } catch (Exception e) {
message = e.getMessage(); message = e.getMessage();
} }
} }
} }

View File

@@ -1,100 +1,260 @@
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.util.Arrays;
public class Stundenplan implements SelectionListener { public class Stundenplan implements SelectionListener {
/** /**
* Main-Methode um das Programm (außerhalb von BlueJ) zu starten. * Main-Methode um das Programm (außerhalb von BlueJ) zu starten.
* *
* @param args * @param args
*/ */
public static void main(String[] args) { public static void main(String[] args) {
// Setzen des "Look & Feel" des Programms // Setzen des "Look & Feel" des Programms
try { try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) { } catch (Exception e) {
} }
// Programm starten // Programm starten
new Stundenplan(); new Stundenplan();
} }
// Instanz des GUI des Programms // Instanz des GUI des Programms
private StundenplanGUI gui; private StundenplanGUI gui;
// Instanz der Datenbankverbindung // Instanz der Datenbankverbindung
private DatabaseConnector dbc; private DatabaseConnector dbc;
/** /**
* Konstruktor des Hauptprogramms * Konstruktor des Hauptprogramms
*/ */
public Stundenplan() { public Stundenplan() {
// Erstellen des GUIs // Erstellen des GUIs
gui = new StundenplanGUI(); gui = new StundenplanGUI();
// Aufbau der Datenbankverbindung // Aufbau der Datenbankverbindung
dbc = new DatabaseConnector("", 0, "stundenplan.db", "", ""); dbc = new DatabaseConnector("", 0, "stundenplan.db", "", "");
QueryResult r; QueryResult r;
// Lehrer abfragen und ein Auswahlfeld erstellen, dass in der // Lehrer abfragen und ein Auswahlfeld erstellen, dass in der
// GUI angezeigt wird, um den angezeigten Stundenplan anzupassen // GUI angezeigt wird, um den angezeigten Stundenplan anzupassen
dbc.executeStatement("SELECT kuerzel FROM lehrer"); dbc.executeStatement("SELECT kuerzel FROM lehrer");
r = dbc.getCurrentQueryResult(); r = dbc.getCurrentQueryResult();
String[] teachers = new String[r.getRowCount()]; String[] teachers = new String[r.getRowCount()];
for (int i = 0; i < r.getRowCount(); i++) { for (int i = 0; i < r.getRowCount(); i++) {
teachers[i] = r.getData()[i][0]; teachers[i] = r.getData()[i][0];
} }
gui.addFilter("Lehrer", teachers); dbc.executeStatement("SELECT jahrgang, buchstabe FROM klassen");
r = dbc.getCurrentQueryResult();
String[] classes = new String[r.getRowCount()];
for (int i = 0; i < r.getRowCount(); i++) {
classes[i] = r.getData()[i][0] + r.getData()[i][1];
}
dbc.executeStatement("SELECT nummer FROM raeume");
r = dbc.getCurrentQueryResult();
String[] raeume = new String[r.getRowCount()];
for (int i = 0; i < r.getRowCount(); i++) {
raeume[i] = r.getData()[i][0];
}
gui.addFilter("Lehrer", teachers);
gui.addFilter("Klasse", classes);
gui.addFilter("Raum", raeume);
// GUI anzeigen und Verhalten bei Interaktion festlegen // GUI anzeigen und Verhalten bei Interaktion festlegen
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.addSelectionListener(this); // GUI ruft Methode selectionChanged auf, wenn sich eine Auswahlbox ändert. gui.addSelectionListener(this); // GUI ruft Methode selectionChanged auf, wenn sich eine Auswahlbox ändert.
gui.setLocationRelativeTo(null); gui.setLocationRelativeTo(null);
gui.setVisible(true); gui.setVisible(true);
} }
/** /**
* Methode um auf Änderungen in der GUi zu reagieren. Sobald der nutzer die * Methode um auf Änderungen in der GUi zu reagieren. Sobald der nutzer die
* Auswahl ändert, wird diese Methode aufgerufen. Der erste Parameter ist der * Auswahl ändert, wird diese Methode aufgerufen. Der erste Parameter ist der
* Name der Auswahlliste, die sich geändert hat (erster Parameter von * Name der Auswahlliste, die sich geändert hat (erster Parameter von
* {@link StundenplanGUI#addFilter(String, String[])} oben) und der zweite ist * {@link StundenplanGUI#addFilter(String, String[])} oben) und der zweite ist
* der neue Wert der Auswahl. * der neue Wert der Auswahl.
* *
* @param pList Name der Auswahlliste * @param pList Name der Auswahlliste
* @param pNewValue Neuer Wert der Auswahl * @param pNewValue Neuer Wert der Auswahl
*/ */
@Override @Override
public void selectionChanged(String pList, String pNewValue) { public void selectionChanged(String pList, String pNewValue) {
if (pList == "Lehrer") { switch (pList) {
// Zuerst alle bisherigen Stunden aus der GUI entfernen case "Lehrer":
gui.removeAllLessons(); // Zuerst alle bisherigen Stunden aus der GUI entfernen
gui.removeAllLessons();
// Neue Daten aus der Datenbank abfragen. // Neue Daten aus der Datenbank abfragen.
// Hier gefakte Daten, die Struktur der Datenbank ist nicht vorgegeben. // Hier gefakte Daten, die Struktur der Datenbank ist nicht vorgegeben.
dbc.executeStatement("SELECT 0,'Q2','405',kuerzel,0,0,'Informatik',-16711936 FROM lehrer WHERE kuerzel = '" + pNewValue + "'"); dbc.executeStatement(
QueryResult r = dbc.getCurrentQueryResult(); "SELECT stunden.tag, stunden.stunde, faecher.name, raeume.nummer, klassen.jahrgang, klassen.buchstabe "
+ "FROM stunden "
+ "JOIN lehrer "
+ "ON lehrer.id = stunden.lehrer_id "
+ "JOIN faecher "
+ "ON faecher.id = stunden.fach_id "
+ "JOIN raeume "
+ "ON raeume.nummer = stunden.raum_nummer "
+ "JOIN klassen "
+ "ON klassen.id = stunden.klasse_id "
+ "WHERE lehrer.kuerzel = '" + pNewValue + "'");
QueryResult r = dbc.getCurrentQueryResult();
// Falls es ein Ergebnis gibt ... // Falls es ein Ergebnis gibt ...
if (r != null) { if (r != null) {
String[][] data = r.getData(); String[][] data = r.getData();
// Neue Stunden in die GUI schreiben // Neue Stunden in die GUI schreiben
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
gui.addLesson( gui.addLesson(
Integer.parseInt(data[i][4]), // Spalte im Plan (0=Montag, ... ,4=Freitag) day(data[i][0]), // Spalte im Plan (0=Montag, ... ,4=Freitag)
Integer.parseInt(data[i][5]), // Zeile im Plan (0=1. Stunde, ... ,9=10. Stunde) Integer.parseInt(data[i][1]), // Zeile im Plan (0=1. Stunde, ... ,9=10. Stunde)
data[i][6], // Titel data[i][2], // Titel
"Raum " + data[i][2], // Untertitel "Raum " + data[i][3], // Untertitel
data[i][1], // Beschreibungstext "Klasse " + data[i][4] + data[i][5], // Beschreibungstext
data[i][3], // Fußzeile "", // Fußzeile
new Color(Integer.parseInt(data[i][7])) // Farbe (Objekt der Klasse Color) color(data[i][2]) // Farbe (Objekt der Klasse Color)
); );
} }
// GUI-Fenster neu zeichnen, um neue Elemente anzuzeigen. // GUI-Fenster neu zeichnen, um neue Elemente anzuzeigen.
gui.revalidate(); gui.revalidate();
gui.repaint(); gui.repaint();
} }
} break;
} case "Klasse":
gui.removeAllLessons();
char jahr = pNewValue.charAt(0);
char letter = pNewValue.charAt(1);
dbc.executeStatement(
"SELECT stunden.tag, stunden.stunde, faecher.name, raeume.nummer, lehrer.kuerzel "
+ "FROM stunden "
+ "JOIN faecher "
+ "ON faecher.id = stunden.fach_id "
+ "JOIN raeume "
+ "ON raeume.nummer = stunden.raum_nummer "
+ "JOIN lehrer "
+ "ON lehrer.id = stunden.lehrer_id "
+ "JOIN klassen "
+ "ON klassen.id = stunden.klasse_id "
+ "WHERE klassen.jahrgang = '" + jahr + "' "
+ "AND klassen.buchstabe = '" + letter + "'");
r = dbc.getCurrentQueryResult();
if (r != null) {
String[][] data = r.getData();
// Neue Stunden in die GUI schreiben
for (int i = 0; i < data.length; i++) {
gui.addLesson(
day(data[i][0]), // Spalte im Plan (0=Montag, ... ,4=Freitag)
Integer.parseInt(data[i][1]), // Zeile im Plan (0=1. Stunde, ... ,9=10. Stunde)
data[i][2], // Titel
"Raum " + data[i][3], // Untertitel
data[i][4], // Beschreibungstext
"", // Fußzeile
color(data[i][2]) // Farbe (Objekt der Klasse Color)
);
}
// GUI-Fenster neu zeichnen, um neue Elemente anzuzeigen.
gui.revalidate();
gui.repaint();
}
break;
case "Raum":
gui.removeAllLessons();
dbc.executeStatement(
"SELECT stunden.tag, stunden.stunde, klassen.jahrgang, klassen.buchstabe, lehrer.kuerzel, faecher.name, raeume.typ, raeume.hat_klavier "
+ "FROM stunden "
+ "JOIN klassen "
+ "ON klassen.id = stunden.klasse_id "
+ "JOIN lehrer "
+ "ON lehrer.id = stunden.lehrer_id "
+ "JOIN faecher "
+ "ON faecher.id = stunden.fach_id "
+ "JOIN raeume "
+ "ON raeume.nummer = stunden.raum_nummer "
+ "WHERE raeume.nummer = '" + pNewValue + "'");
r = dbc.getCurrentQueryResult();
if (r != null) {
String[][] data = r.getData();
// Neue Stunden in die GUI schreiben
for (int i = 0; i < data.length; i++) {
gui.addLesson(
day(data[i][0]), // Spalte im Plan (0=Montag, ... ,4=Freitag)
Integer.parseInt(data[i][1]), // Zeile im Plan (0=1. Stunde, ... ,9=10. Stunde)
data[i][2] + data[i][3], // Titel
data[i][4], // Untertitel
data[i][5], // Beschreibungstext
"(" + data[i][6] + (Integer.parseInt(data[i][7]) == 1 ? " + hat Klavier :" : "") + ")", // Fußzeile
color(data[i][5]) // Farbe (Objekt der Klasse Color)
);
}
// GUI-Fenster neu zeichnen, um neue Elemente anzuzeigen.
gui.revalidate();
gui.repaint();
}
break;
}
}
private int day(String day) {
switch (day) {
default:
case "mo":
return 0;
case "di":
return 1;
case "mi":
return 2;
case "do":
return 3;
case "fr":
return 4;
}
}
private Color color(String fach) {
switch (fach) {
default:
case "Mathe":
return Color.BLUE;
case "Deutsch":
return Color.RED;
case "Englisch":
return new Color(0, 0, 160);
case "Latein":
return Color.CYAN;
case "Franzoesisch":
return Color.CYAN;
case "Geschichte":
return Color.GREEN;
case "Politik":
return Color.GRAY;
case "Biologie":
return Color.GREEN;
case "Chemie":
return Color.WHITE;
case "Physik":
return Color.BLACK;
case "Informatik":
return Color.BLACK;
case "Philosophie":
return Color.MAGENTA;
case "Musik":
return Color.YELLOW;
case "Kunst":
return Color.LIGHT_GRAY;
case "Sport":
return Color.ORANGE;
}
}
} }

View File

@@ -184,7 +184,8 @@ public class StundenplanGUI extends JFrame implements ActionListener {
*/ */
public void actionPerformed(ActionEvent pActionEvent) { public void actionPerformed(ActionEvent pActionEvent) {
if (this.selectionListener != null) { if (this.selectionListener != null) {
JComboBox<String> source = ((JComboBox<String>) pActionEvent.getSource()); @SuppressWarnings("unchecked")
JComboBox<String> source = ((JComboBox<String>) pActionEvent.getSource());
String newValue = (String) source.getSelectedItem(); String newValue = (String) source.getSelectedItem();
String sourceName = source.getName(); String sourceName = source.getName();