In dieser Aufgabe soll eine IMDb-Keyword-Suche gebaut werden. Dabei soll ein Java-Programm geschrieben werden, das ein Keyword entgegennimmt und alle Filme und Schauspieler(innen) ausgibt, in deren Namen dieses Keyword enthalten ist. Der Zugriff auf die Datenbank erfolgt über JDBC.
Hier zwei Beispiele, die die gewünschte Ausgabe darstellen:
Beispiel 1: Keyword = Krug
java ImdbSuche \
-d db2db1 \
-s 127.0.0.1 \
-p 50001 \
-u db2inst1 \
-pw ws2011 \
-k Krug
Erwartete Ausgabe:
MOVIES
ACTORS
Krug, Manfred
PLAYED IN
Tatort - Leiche im Keller
Tatort - Lockvögel
Tatort - Rattenlinie
CO-STARS
Brauer, Charles (3)
Hart, Kurt (2)
Hoppe, Edgar (2)
Martens, Dirk (I) (2)
Becker, Rolf (1)
Beispiel 2: Keyword = Blacks
java ImdbSuche \
-d db2db1 \
-s 127.0.0.1 \
-p 50001 \
-u db2inst1 \
-pw ws2011 \
-k Blacks
Erwartete Ausgabe:
MOVIES
Blacksmith, The, 1922, Comedy, Short
Fox, Virginia
Keaton, Buster
Roberts, Joe (I)
ACTORS
Blackshaw, Anthony
PLAYED IN
Fiction Makers, The
CO-STARS
Armitage, Graham (1)
Ashmore, Peter (1)
Ball, Ralph (1)
Boyd, Roy (1)
Clegg, Tom (1)
Programmablauf
Der Benutzer soll das Programm mit folgenden Parametern starten können:
-d <Datenbankname>
-s <IP-Adresse des Datenbank-Servers>
-p <Port der Datenbank-Instanz>
-u <Username>
-pw <Passwort>
-k <Keyword>
Das Programm stellt mittels JDBC eine Verbindung zur Datenbank her (3P) und ermittelt alle notwendigen Informationen, um folgende Ausgabe zu ermöglichen:
- Die Ausgabe beginnt mit dem Teil MOVIES. Hier sollen alle Filme gelistet werden, in denen das Keyword im Titel vorkommt. Die Ausgabe ist aufsteigend sortiert nach dem Titel. (1P)
- Für jeden Film wird ausgegeben:
- Der Titel, das Jahr, und alle Genres des Films (jeweils durch Komma getrennt). (2P)
- Außerdem umfasst die Ausgabe für jeden Film die beteiligten Schauspieler(innen), sortiert nach dem Namen. Es werden jedoch nur die ersten fünf ausgegeben. (3P)
- Im zweiten Teil ACTORS werden alle Schauspieler(innen) ausgeben, in deren Namen das gegebene Keyword vorkommt. Das Ergebnis soll dabei aufsteigend nach den gefundenen Namen sortiert werden. (2P)
- Für jede(n) Schauspieler(in) wird ausgegeben:
- Alle Filme, in denen der Schauspieler mitgewirkt hat (PLAYED IN). (3P)
- Die Schauspieler(innen), die in denselben Filmen mitgewirkt haben (CO-STARS). Hinter jedem/-r Schauspieler(in) steht in Klammern die Anzahl der Filme, in denen beide mitgespielt haben. Es sollen die Top 5 ausgegeben werden, sortiert nach Anzahl gemeinsamer Filme, dann nach Name. (6P)
Weitere Hinweise:
- Alle Ausgaben sollen grundsätzlich nur einmal erfolgen (z.B. sollen keine Filme doppelt ausgegeben werden).
- Der Name eines Schauspielers kennzeichnet ihn eindeutig.
- Die Nutzung von PreparedStatements wird empfohlen. Vergleicht testweise die Performance mit normalen Statements für häufig aufgerufene Anfragen. Abgabeform
- Es soll eine Java-Klasse abgegeben werden.
- Es soll die Ausgabe folgender Anfragen angegeben werden: – Keyword = Prior – Keyword = Schwarz
// # Execute: // javac ImdbSuche.java // java ImdbSuche import java.sql.*; import java.util.*; public class ImdbSuche { static Connection con; public static void log (Object line) { System.out.println(line); } public static void main (String[] args) { // Defaults String databaseName = "db2db1"; String serverIp = "192.168.189.128"; String port = "50001"; String username = "db2inst1"; String password = "ws2011"; String keyword = "Schwarz"; // No switch to increase compatibility (switch needs jdk > 7) for (int i = 0; i < args.length; i++) { if (args[i].equals("-d")) databaseName = args[i + 1]; else if (args[i].equals("-s")) serverIp = args[i + 1]; else if (args[i].equals("-p")) port = args[i + 1]; else if (args[i].equals("-u")) username = args[i + 1]; else if (args[i].equals("-pw")) password = args[i + 1]; else if (args[i].equals("-k")) keyword = args[i + 1]; } connect( serverIp, port, databaseName, username, password ); Dictionary[] movies = queryDbForMoviesWithKeyword(keyword); log("MOVIES"); for (int i = 0; i < movies.length; i++) { log( movies[i].get("TITLE") + ", " + movies[i].get("YEAR") + movies[i].get("GENRE") ); Dictionary[] actors = queryDbForActorsWithMovie( movies[i].get("TITLE").toString() ); for (int j = 0; j < actors.length; j++) { log("\t" + actors[j].get("NAME")); } } log("\nACTORS"); Dictionary[] actors = queryDbForActorsWithKey(keyword); for (int i = 0; i < actors.length; i++) { log(actors[i].get("NAME")); log("\tPLAYED IN"); Dictionary[] films = queryDbForFilmsWithActor( actors[i] .get("NAME") .toString() ); for (int j = 0; j < films.length; j++) { log("\t\t" + films[j].get("TITLE")); } log("\tCO-STARS IN"); Dictionary[] costars = queryDbForCoStarsWithActor( actors[i] .get("NAME") .toString() ); for (int j = 0; j < costars.length; j++) { log( "\t\t" + costars[j].get("NAME") + " (" + costars[j].get("ANZAHL") + ")" ); } } } @SuppressWarnings("unchecked") public static Dictionary[] queryDbForMoviesWithKeyword (String key) { String query = "SELECT DISTINCT title, year, mid" + "FROM movie " + "WHERE title " + "LIKE '%" + key + "%' " + "ORDER BY title ASC"; Dictionary[] movies = query(query); for (Dictionary movie : movies) { query = "SELECT DISTINCT genre " + "FROM genre " + "WHERE movie_id " + "LIKE '" + movie.get("MID") + "%' " + "ORDER BY genre ASC"; Dictionary[] genresResult = query(query); String genreString = ""; for (int i = 0; i < genresResult.length; i++) genreString += ", " + ((String) genresResult[i].get("GENRE")); movie.put("GENRE", genreString); } return movies; } public static Dictionary[] queryDbForActorsWithMovie(String key) { String query = "SELECT DISTINCT name " + "FROM (" + "(SELECT name FROM Actor " + "WHERE movie_id LIKE '%" + key + "%' ORDER BY name ASC) " + "UNION " + "(SELECT name FROM Actress " + "WHERE movie_id LIKE '%" + key + "%' ORDER BY name ASC)) " + "ORDER BY name ASC FETCH FIRST 5 ROWS ONLY"; Dictionary[] actors = query(query); return actors; } public static Dictionary[] queryDbForActorsWithKey (String key) { String query = "SELECT DISTINCT name " + "FROM " + "((SELECT name FROM Actor " + "WHERE name LIKE '%" + key + "%' ORDER BY name ASC) " + "UNION " + "(SELECT name FROM Actress " + "WHERE name LIKE '%" + key + "%' ORDER BY name ASC)) " + "ORDER BY name ASC"; Dictionary[] actors = query(query); return actors; } public static Dictionary[] queryDbForFilmsWithActor (String key) { String query = "SELECT DISTINCT title, mid " + "FROM " + "((SELECT name, movie_id FROM Actor " + "WHERE name LIKE '%" + key + "%' ORDER BY name ASC) " + "UNION " + "(SELECT name, movie_id FROM Actress " + "WHERE name LIKE '%" + key + "%' ORDER BY name ASC)) " + "AS actors, movie " + "WHERE movie.mid = actors.movie_id " + "ORDER BY title ASC"; Dictionary[] films = query(query); return films; } public static Dictionary[] queryDbForCoStarsWithActor (String key) { String query = "SELECT name, COUNT(*) AS Anzahl " + "FROM (SELECT mid FROM " + "((SELECT name, movie_id FROM Actor " + "WHERE name LIKE '%" + key + "%' ORDER BY name ASC) " + "UNION " + "(SELECT name, movie_id FROM Actress " + "WHERE name LIKE '%" + key + "%' ORDER BY name ASC)) " + "AS actors, movie WHERE movie.mid = actors.movie_id) " + "AS movies, ((SELECT * FROM actor WHERE name NOT LIKE '"+key+"') " + "UNION (SELECT * FROM actress WHERE name NOT LIKE '"+key+"')) " + "AS actors WHERE movies.mid = actors.movie_id GROUP " + "BY actors.name ORDER BY Anzahl, Name FETCH FIRST 5 ROWS ONLY"; Dictionary[] films = query(query); return films; } public static void connect( String ip, String port, String db_name, String user, String password ){ try { Class .forName("com.ibm.db2.jcc.DB2Driver") .newInstance(); String URL = "jdbc:db2://" + ip + ":" + port + "/" + db_name; Connection con = DriverManager.getConnection(URL, user, password); ImdbSuche.con = con; } catch (Exception error) { log(error); } } @SuppressWarnings("unchecked") public static Dictionary[] query (String query) { ArrayList<Dictionary> list = new ArrayList<Dictionary>(); try { /* // Slow Statement stmt = con.createStatement(); ResultSet resultSet = stmt.executeQuery(query); */ // Fast PreparedStatement pstmt = con.prepareStatement(query); ResultSet resultSet = pstmt.executeQuery(); while (resultSet.next()) { // Put it into a dictionary ResultSetMetaData rsmd = resultSet.getMetaData(); int columnCount = rsmd.getColumnCount(); Dictionary dict = new Hashtable(); for (int i = 1; i <= columnCount; i++) { String name = rsmd.getColumnName(i); dict.put(name, resultSet.getString(i)); } list.add(dict); } } catch (Exception error) { log(error); } return list.toArray(new Dictionary[list.size()]); } }
Keyword = Prior
java ImdbSuche \ -d db2db1 \ -s 192.168.189.128 \ -p 50001 \ -u db2inst1 \ -pw ws2011 \ -k Prior
MOVIES ACTORS Prior, Herbert PLAYED IN Martyrdom of Philip Strong, The Next Unsullied Shield, An CO-STARS IN Connery, Van (1) Cooper, Bigelow (1) Dawley, Janet (1) Edwin, Walter (1) Eytinge, Harry (1) Prior, Tom PLAYED IN Warning: Parental Advisory CO-STARS IN Adair, Dwight (1) Amiss, Susannah (1) Beatty, Jim (1) Berryman, Joe (1) Born, David (1)
Keyword = Schwarz
java ImdbSuche \ -d db2db1 \ -s 192.168.189.128 \ -p 50001 \ -u db2inst1 \ -pw ws2011 \ -k Schwarz
MOVIES Tatort - Schwarzer Advent, 1998, Crime Berkel, Christian Erhart, Peter Fitz, Michael (I) Grosser, Renate Hartmann, Alexandra ACTORS Schwarz, Josef PLAYED IN Meister Eder und sein Pumuckl CO-STARS IN Ackermann, Kathrin (1) Astor, Eva (1) Basedow, Rainer (1) Baumgartner, Monika (1) Bayrhammer, Gustl (1) Schwarz, Norbert PLAYED IN Es geht seinen Gang oder M?hen in unserer Ebene CO-STARS IN Bathke, Wolfgang (1) Bauer, Reinhard Vom (1) Behrends, Ela (1) Branding, Heinz Theo (1) Gissel, Henning (1) Schwarzkopf, Klaus PLAYED IN Meister Eder und sein Pumuckl CO-STARS IN Ackermann, Kathrin (1) Astor, Eva (1) Basedow, Rainer (1) Baumgartner, Monika (1) Bayrhammer, Gustl (1)
Anmerkung: Die Co-Stars sollten zuerst nach der Anzahl gemeinsamer Filme sortiert werden.
HPI, 2015-06-29, Datenbanksysteme 1, Aufgabe 4.2
2015-07-27 13:28:54 UTC
2015-07-27 13:30:41 UTC