Vorlesung Datenbanken Wintersemester 2007/08 6 Web–Datenbanken Web–Datenbank–Anbindungen: Servlets Applets JAVA–Server Pages Prof. Dr. Dietmar Seipel Sprachen: JAVA, P HP, Python, 481 Vorlesung Datenbanken 6.1 Wintersemester 2007/08 Web–Datenbank–Anbindungen mit Servlets JAVA–Servlets können über eine parametrisierte URL (Uniform Resource Locator) aufgerufen werden. Um die Skalierbarkeit der Architektur auch für sehr große Benutzerzahlen zu gewährleisten, bearbeitet die Servlet–Engine die Anforderungen parallel in mehreren voneinander unabhängigen Threads (leichtgewichtigen Prozessen). Derartig erweiterte Sofwaresysteme (meist in Kombination mit einem Web–Server) werden auch als Anwendungs–Server (Application Server) bezeichnet. Prof. Dr. Dietmar Seipel 482 Vorlesung Datenbanken Wintersemester 2007/08 Das Servlet realisiert eine Methode doGet (oder doPost): Aufbau der Datenbankverbindung mittels J DBC Auswertung der Anfrage Generierung der H TML–Seite, die an den Browser geschickt wird Die für die Formulierung der Datenbank–Anfrage notwendigen Parameter werden clientseitig über eine Formularschnittstelle ermittelt. Sie werden dem Servlet als HttpServletRequest–Objekt übergeben. Das Servlet kann einen Paramenter Par dann mittels request.getParameter("Par") ermitteln. Das generierte H TML–Dokument wird über ein PrinterWriter–Objekt an das HttpServletResponse–Objekt übergeben. Prof. Dr. Dietmar Seipel 483 Vorlesung Datenbanken Wintersemester 2007/08 Prof. Dr. Dietmar Seipel 484 Vorlesung Datenbanken Wintersemester 2007/08 Anfrage–Seite in H TML: <html> <head><title>Employees over a given Income</title></head> <body> <h1>Employees over a given Income</h1> <blockquote> <form action="https:/www.xyz.de/servlets/EmployeeSalary" method="GET"> Please enter the minimum salary: <br> <input type="TEXT" name="salary"/> <br> <input type="SUBMIT" value="Submit Query"/> </form> </blockquote> </body> </html> Prof. Dr. Dietmar Seipel 485 Vorlesung Datenbanken Wintersemester 2007/08 GET–Methode Bei Verwendung der HTTP GET–Methode werden die Parameter vom Web–Browser als Teil der URL an das Servlet übergeben, z.B.: https:/www.xyz.de/servlets/EmployeeSalary?salary=30000 Den Parameter–Teil (hinter dem Zeichen “?”) einer derartigen URL bezeichnet man oft als Query–String. Mehrere Parameter/Wert–Paare könnnen mittels “&” getrennt übergeben werden. POST–Methode Bei Verwendung der alternativen HTTP POST–Methode werden die Parameter vom Web–Browser unsichtbar an das Servlet transferiert; sie sind also nicht Teil der URL. Prof. Dr. Dietmar Seipel 486 Vorlesung Datenbanken Wintersemester 2007/08 JAVA–Servlet: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.sql.*; import java.text.*; public class EmployeeSalary extends HttpServlet { public void doGet ( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { protected Connection con = null; initConnection(); response.setContentType("text/html"); PrintWriter out = response.getWriter(); String Salary = request.getParameter("salary"); generateHtmlTable(Salary); } } Prof. Dr. Dietmar Seipel 487 Vorlesung Datenbanken Wintersemester 2007/08 private void generateHtmlTable ( String Salary ) { printHtmlHeader(Salary); try { String query = "SELECT * FROM employee " + "WHERE salary >= ’" + Salary + "’"; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { out.println( "<tr><td>" + rs.getString("Fname") + "</td><td>" + rs.getString("Minit") + "</td><td>" + rs.getString("Lname") + "</td><td>" + rs.getString("Salary") + "</td></tr>" ); } } catch (Exception mye){ out.println(mye.toString()); } printHtmlBottom(); } Prof. Dr. Dietmar Seipel 488 Vorlesung Datenbanken Wintersemester 2007/08 Resultat der Anfrage: <html> <head><title>Employees earning at least 30000 USD</title></head> <body> <table border="1" cellpadding="5"> <tr><th>Fname</th><th>Minit</th><th>Lname</th><th>Salary</th></tr> <tr><td>John</td><td>B</td><td>Smith</td><td>30000</td></tr> <tr><td>Franklin</td><td>T</td><td>Wong</td><td>40000</td></tr> <tr><td>Jennifer</td><td>S</td><td>Wallace</td><td>43000</td></tr> <tr><td>Ramesh</td><td>K</td><td>Narayan</td><td>38000</td></tr> <tr><td>James</td><td>E</td><td>Borg</td><td>55000</td></tr> </table> </body> </html> Prof. Dr. Dietmar Seipel 489 Vorlesung Datenbanken Wintersemester 2007/08 Resultat der Anfrage im Browser: Prof. Dr. Dietmar Seipel 490 Vorlesung Datenbanken Wintersemester 2007/08 H TML–Seite mit Servlet–Aufrufen: <html> <head><title>Employees over a given Income</title></head> <body> <h1>Employees over a given Income</h1> <ul> <li> <a href=".../servlets/EmployeeSalary?salary=0"> list all employess </a> </li> <li> <a href=".../servlets/EmployeeSalary?salary=30000"> list employess over 30000 USD </a> </li> <li> <a href=".../servlets/EmployeeSalary?salary=60000"> list employess over 60000 USD </a> </li> </ul> </body> </html> Prof. Dr. Dietmar Seipel 491 Vorlesung Datenbanken Wintersemester 2007/08 Prof. Dr. Dietmar Seipel 492 Vorlesung Datenbanken Wintersemester 2007/08 Web–Datenbank–Anbindungen mit JAVA–Applets Applets sind JAVA–Programme, die am Web–Klienten ausgeführt werden. Es handelt sich also um mobilen Code, der vom Web–Server auf den Klienten übertragen und dort ausgeführt wird. Prof. Dr. Dietmar Seipel 493 Vorlesung Datenbanken Wintersemester 2007/08 6.2 JAVA–Server Pages H TML–Seiten, die sowohl aus statischen als auch aus dynamisch generierten Teilen bestehen JAVA Server Pages (JSPs) erlauben die Einbettung von JAVA–Code–Fragmenten in eine H TML–Seite. Der Web–Server initiiert deren Ausführung, bevor die Seite an den Klienten übertragen wird. Vorteil: Die Visualisierung, d.h. der H TML–Code, liegt statisch in einem Dokument vor. Die JAVA–Code–Fragmente können als Komponenten (JAVA–Beans) in separaten Dateien vorliegen. Dies erhöht die Übersichtlichkeit und die Wiederverwendbarkeit. Microsoft bietet alternativ Active Server Pages (ASPs) an. Prof. Dr. Dietmar Seipel 494 Vorlesung Datenbanken Wintersemester 2007/08 5 zusätzliche Tags: <%@page Attribute der Direktive%> Steuerung des Übersetzungsvorgangs der JSP–Seiten mittels unterschiedlicher Attribute <%!Deklaration%> z.B. eine JAVA–Operation, die dann später in der Seite mehrfach verwendet wird <%=Ausdruck%> entspricht <% out.print(Ausdruck) %> <%Java-Code-Fragment%> <%--Komentar--%> wird nicht in das erzeugte H TML–Dokument übernommen Prof. Dr. Dietmar Seipel 495 Vorlesung Datenbanken Wintersemester 2007/08 JAVA–Server Page mit JAVA–Code: <%@page import="java.sql.*"%> <%!Connection con = null;%> <%initConnection();%> <%!String generateHtmlTable(String Salary) ...%> <html> <head><title>Employees over a given Income</title></head> <body> <ul> <li> 0 <%=generateHtmlTable("0")%> </li> <li> 30000 <%=generateHtmlTable("30000")%> </li> <li> 60000 <%=generateHtmlTable("60000")%> </li> </ul> </body> </html> Prof. Dr. Dietmar Seipel 496 Vorlesung Datenbanken Wintersemester 2007/08 String generateHtmlTable(String Salary) { StringBuffer result = new StringBuffer(); result.append("<table>"); try { String query = "SELECT * FROM employee " + "WHERE salary >= ’" + Salary + "’"; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { result.append( "<tr><td>" + rs.getString("Fname") + "</td><td>" + rs.getString("Minit") + "</td><td>" + rs.getString("Lname") + "</td><td>" + rs.getString("Salary") + "</td></tr>" ); } } catch (Exception mye){ result.append(mye.toString()); } result.append("</table>"); return result.toString(); } Prof. Dr. Dietmar Seipel 497 Vorlesung Datenbanken Wintersemester 2007/08 JAVA–Server Page mit JAVA–Bean–Aufruf: <%@page import="jspdemo.EmployeeBean"%> <jsp:useBean id="mybean" class="jspdemo.EmployeeBean" scope="application"/> <html> <head><title>Employees over a given Income</title></head> <body> <ul> <li> 0 <%=mybean.generateHtmlTable("0")%> </li> <li> 30000 <%=mybean.generateHtmlTable("30000")%> </li> <li> 60000 <%=mybean.generateHtmlTable("60000")%> </li> </ul> </body> </html> Prof. Dr. Dietmar Seipel 498 Vorlesung Datenbanken Wintersemester 2007/08 JAVA–Bean: package jspdemo; import java.sql.*; public class EmployeeBean { Connection con = null; public EmployeeBean() { initConnection(); } public String generateHtmlTable(String Salary) ... } Es muß einen parameterlosen Konstruktor geben. Prof. Dr. Dietmar Seipel 499 Vorlesung Datenbanken Wintersemester 2007/08 Die JSP–Seite wird übersetzt in ein Servlet. Der Browser fordert die JSP–Seite an. Der Web–Server initiiert die Ausführung des generierten Servlets. Bei der Ausführung werden die JAVA–Code–Fragmente (inklusive der Tags für die Ausdrucke) eliminiert, und es werden an deren Stelle die bei der Ausführung generierten Ergebnisse eingefügt. Es entsteht eine reine H TML–Seite, die an den Klienten geschickt wird. Der Web–Browser zeigt diese Seite an. Prof. Dr. Dietmar Seipel 500 Vorlesung Datenbanken Wintersemester 2007/08 6.3 Web–Datenbank Anbindungen in P HP P HP wurde urprünglich als Skriptsprache designed, um H TML zu generieren funktionale Sprache, seit P HP Version 4 objektorientiert sehr breite Unterstützung von Seiten der Provider (klassische Umgebung: Apache / P HP4 bzw. P HP5 / MySQL) geringere Wartungs– und Entwicklungskosten als bei Servlet–Anwendungen Prof. Dr. Dietmar Seipel 501 Vorlesung Datenbanken Wintersemester 2007/08 Datenbanken können in P HP in zwei Varianten angesprochen werden: direkt über die P HP–Schnittstellen–Implementation der Datenbank (z.B.: php-mysql) über die P EAR–Datenbankschnittstelle (P HP Extension and Application Repository) P EAR dient als Abstraktionlayer in P HP und unterstützt (fast) alle gängigen Datenbanktypen, wie Prof. Dr. Dietmar Seipel MyS QL, PostgreS QL, Oracle 7/8/8i, Interbase, O DBC, Microsoft S QL, 502 Vorlesung Datenbanken Wintersemester 2007/08 P EAR–Datenbankmodell als Abstraktionslayer: Vorteil: unabhängig von Datenbank–spezifischen Erweiterungen, damit leicht portierbar (z.B. von Mysql nach Postgres) Nachteil: Verzicht auf Datenbank–spezifische Features (z.B. View–Mechanismen unter Postgres) Beispiel: Verbindungsaufbau über DSN (data source names): mysql://user:very_secret@localhost/company Query Verbindungsabbau Prof. Dr. Dietmar Seipel 503 Vorlesung Datenbanken Wintersemester 2007/08 <?php require_once(’DB.php’); // $dsn = array( ’phptype’ => ’mysql’, ’username’ => ’user’, ’password’ => ’very_secret’, ’hostspec’ => ’localhost’, ’database’ => ’company’ ); $db =& DB::connect($dsn); if(PEAR::isError($db)){ die($db->getMessage()); } $sql = "SELECT * FROM employee"; $result =& $db->query($sql); if(PEAR::isError($result)){ die $result->getMessage(); } while($result->fetchInto($row)){ // $row: Array aus Ergebnisdaten } $db->disconnect(); ?> Prof. Dr. Dietmar Seipel 504 Vorlesung Datenbanken Wintersemester 2007/08 Gleiches Beispiel (JAVA–like): <?php ... $db = new DB(); $connection = $db->connect($dsn); if(PEAR::isError($connection)){ die($connection->getMessage()); } ... $result = $connection->query($sql); ... while($row = $result->fetchRow()){ // ... } $connection->disconnect(); ?> Prof. Dr. Dietmar Seipel 505 Vorlesung Datenbanken Wintersemester 2007/08 Anfrage: Prepare und Execute Statements <?php // Standard Query $result = $db->query( "SELECT * FROM employee WHERE SALARY >= 30000"); // Prepared Query mit Skalar $prepared = $db->prepare( "SELECT * FROM employee WHERE SALARY >= ?"); $result = $db->execute($prepared, 30000); // Prepared Query mit Arrays $prepared = $db->prepare( "SELECT * FROM employee WHERE SALARY >= ? AND SEX = ’?’"); $result = $db->execute($prepared, array(30000, ’F’)); // Prepared Statement fuer mehrere Abfragen $prepared = $db->prepare( "SELECT * FROM employee WHERE SALARY >= ? AND SEX = ’?’"); $data = array(array(30000, ’F’), array(30000, ’M’)); $results = $db->executeMultiple($prepared, $data); foreach ($results as $result){ // ... } ?> Prof. Dr. Dietmar Seipel 506 Vorlesung Datenbanken Wintersemester 2007/08 Query: autoPrepare() und autoExecute() autoPrepare generiert vollständige U PDATE– oder I NSERT–Statements autoExecute generiert und führt U PDATE– oder I NSERT–Statements aus Query Modus gesetzt durch – DB_AUTOQUERY_INSERT bzw. – DB_AUTOQUERY_UPDATE Prof. Dr. Dietmar Seipel 507 Vorlesung Datenbanken Wintersemester 2007/08 Beispiel: John Smith bekommt eine Gehaltserhöhung, in S QL: UPDATE employee SET SALARY=40000 WHERE SSN = ’123456789’’’; <?php $field_values = array(’SALARY’ => 40000); $result = $db->autoExecute( ’employee’, // Tabelle $field_values, // Werte DB_AUTOQUERY_UPDATE, // Mode "SSN=’123456789’" // WHERE--Bedingung ); // oder: $field_names = array(’SALARY’); $field_values = array(’40000’); $prepared = $db->autoPrepare( ’employee’, $field_names, DB_AUTOQUERY_UPDATE, "SSN = ’123456789’"); $result =& $db->execute($prepared, $field_values); ?> Prof. Dr. Dietmar Seipel 508 Vorlesung Datenbanken Wintersemester 2007/08 Ergebnismengen von Anfragen gespeichert als indiziertes Array: <?php while($row = $result->fetchRow()){ //$row indiziert } ?> assoziiertes Array (der Array–Index entspricht dem DB–Spaltenindex): <?php $db->setFetchMode(DB_FETCHMODE_ASSOC); while($row = $result->fetchRow()){ echo $row[’FNAME’]; echo $row[’LNAME’]; echo $row[’SEX’]; echo $row[’SALARY’]; } ?> Prof. Dr. Dietmar Seipel 509 Vorlesung Datenbanken Wintersemester 2007/08 Literatur: Rasmus Lerdorf, Kevin Tatroe: Programming P HP, O’Reilly–Verlag, 2002/1. P EAR Online Manual: http://pear.php.net/manual/en/ Prof. Dr. Dietmar Seipel 510