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:

  1. 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)
  2. Für jeden Film wird ausgegeben:
    1. Der Titel, das Jahr, und alle Genres des Films (jeweils durch Komma getrennt). (2P)
    2. 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)
  3. 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)
  4. Für jede(n) Schauspieler(in) wird ausgegeben:
    1. Alle Filme, in denen der Schauspieler mitgewirkt hat (PLAYED IN). (3P)
    2. 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
Solution
  • // # 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.

  • URL:
  • Language: Deutsch
  • Subjects: Databases
  • Type: Describe
  • Duration: 90min
  • Credits: 20
  • Difficulty: 0.7
  • Tags: java sql search
  • Note:
    HPI, 2015-06-29, Datenbanksysteme 1, Aufgabe 4.2
  • Created By: ad-si
  • Created At:
    2015-07-27 13:30:41 UTC
  • Last Modified:
    2015-07-27 13:30:41 UTC