Kai Jannaschk || [email protected] DATENBANKEN UND SWENTWICKLUNG 03.06.2008 JDBC, SQLJ, O/R-Mapping Motivation Reine SQL bietet keine intuitive Benutzerschnittstelle Geringe Möglichkeiten der Ablaufsteuerung und Bedingungskontrolle Realisierung von Algorithmen in Programmiersprachen Überwachung und Erzwingung von Integritätsbedingungen in DBMS unterschiedlich Kai Jannaschk || [email protected] 03.06.2008 Stored Procedure Kai Jannaschk || [email protected] 03.06.2008 Stored Procedure Funktionen im DBMS Kapselung des direkten Zugriffes auf Tabellen durch Applikationen mgl. Unterstützt Befehle zur Ablaufsteuerung und/oder Auswertung von Bedingungen Vergleichbar mit Makros Geschwindigkeitsvorteil gegenüber einfachen SQLAnfragen, da Syntaxprüfung und Prüfung auf logische Korrektheit bei Aufruf nicht mehr nötig und Ablaufplan bereits im DBMS hinterlegt Kai Jannaschk || [email protected] 03.06.2008 Aufbau Stored Procedure create or replace procedure newPart( pno IN OUT char, thePrice IN OUT NUMBER, part_description IN varchar, quantity_on_hand IN OUT integer, reorder IN OUT integer ) as newPno CHAR(8); quan integer := 0; BEGIN newPno := UPPER(pno); IF (quantity_on_hand IS NOT NULL) THEN quan := quantity_on_hand; END IF; IF (reorder IS NULL) THEN reorder := 10; END IF; INSERT INTO INVENTORY (PART_NUMBER, DESCRIPTION, PRICE, QUANTITY_ON_HAND, REORDER_QUANTITY) VALUES (newPno, part_description, thePrice, quan, reorder); SELECT PART_NUMBER, PRICE, QUANTITY_ON_HAND,REORDER_QUANTITY INTO pno, thePrice, quantity_on_hand, reorder FROM INVENTORY WHERE PART_NUMBER = newPno; END Kai Jannaschk || [email protected] 03.06.2008 JDBC Funktionsweise Aufbau Implementierung Kai Jannaschk || [email protected] 03.06.2008 Schritte 1. 2. 3. 4. 5. 6. Laden des Treibers Herstellen einer Verbindung zur Datenquelle Vorbereiten einer Abfrage Ausführen einer Abfrage Auswerten von Ergebnissen Schließen der Verbindung zur Datenquelle Kai Jannaschk || [email protected] 03.06.2008 JDBC Driver Types Kai Jannaschk || [email protected] 03.06.2008 1. Laden des Treibers JDBC-Treiber Bibliothek mit Implementierung der Interfaces „java.sql“ und “javax.sql“ Hauptklasse implementiert Interface „java.sql.Driver“ Abschluss des Ladens eines Treibers erfolgt mit Registrierung des Treibers beim Treibermanager try { Class.forName(”com.ibm.db2.jcc.DB2Driver”); } catch (ClassNotFoundException e) { // Fehlerbehandlung, falls Klasse nicht // gefunden wurde } Kai Jannaschk || [email protected] 03.06.2008 2. Herstellen einer Verbindung DB-Verbindung entspricht einem Objekt vom Typ Connection Dient zur Erzeugung von Statements Parameter: URL jdbc:<dialect>://<host>:<port>/<database>:<parameter> ~ ist DBMS spezifisch Nutzername für DB Passwort für Nutzer der DB mgl. Methodenaufrufe Connection con = DriverManager.getConnection( String url String url, String user, String passwd ); Kai Jannaschk || [email protected] 03.06.2008 3. Vorbereiten einer Abfrage Kapselung von Abfragen im Objekt Statement Jede Abfrage in eigenem Statement Verarbeitung eines Ergebnisses vor Absenden einer neuen Abfrage mit erzeugten Statement-Objekt 3 Typen von Statements Einfaches Statement: statisches Statenment; Kompilierung in DBMS zur Laufzeit PreparedStatement: Vorbereiten eines Statements mit Möglichkeit zur Angabe von Parametern Prüfung der Gültigkeit von Parameterwerten in DBMS PreparedStatement stmt = con.preparedStatement(String Statement stmt = con.createStatement(); sql); Callable Statement: Aufruf von z.B. Stored Procedures in der DB CallableStatement stmt = con.preparedStatement(String sql); Kai Jannaschk || [email protected] 03.06.2008 4. Ausführen einer Abfrage Augenmerk auf 2 Fkt. stmt.executeUpdate(<String sql>); DDL & DML ResultSet result = executeQuery(<String sql>); Bsp. preparedStatement: String sql = „select nachname from Student where matrikel like ?“; PreparedStatement stmt = con.preparedStatement(sql); stmt.setString(1,’81%‘); ResultSet result = stmt.executeQuery(); Kai Jannaschk || [email protected] 03.06.2008 5. Auswerten des Ergebnisses Ergebnismenge i.d.R. forward-only, not updatable Durchlauf durch Ergebnismenge nach Iterator-Pattern Zeiger auf Tupel der Ergebnismenge Zugriff auf einzelne Attributwerte des Tupels mittels get<Standarddatentyp>() Bsp.: while (result.next()) { System.out.println(result.getString(„nachname“)); System.out.println(result.getString(1)); } Kai Jannaschk || [email protected] 03.06.2008 6. Schließen der Verbindung Nach Abschluss freigeben der nicht mehr benötigten Objekte ResultSet, Statement, Connection result.close(); stmt.close(); con.close(); Kai Jannaschk || [email protected] 03.06.2008 Hinweise Nutzung von Metadaten Verarbeitung von Ergebnismengen Connection.getMetaData(): Informationen über die DB im Allgemeinen (Tab-Struktur, Prozeduren, …) ResultSet.getMetaData(): Informationen über Ergebnismenge (Attributsnamen, Datentypen, …) Beliebiges Setzen eines Zeigers innerhalb der Ergebnismenge Änderbarkeit des Ergebnisses Transaktionen Standard: jede SQL-Anweisung in eigener Transaktion Gezieltes Abspeichern bzw. Rollback von DB-Transaktionen Kai Jannaschk || [email protected] 03.06.2008 SQLJ Typen Aufbau Vergleich zu JDBC Kai Jannaschk || [email protected] 03.06.2008 Typen von SQLJ SQLJ Teil 0: Einbettung von SQL in JavaProgrammen mit standardisierter Syntax und Semantik SQLJ Teil 1: Implementierung von Prozeduren und Funktionen in Java zur Speicherung und Ausführung in DBMS SQLJ Teil 2: Möglichkeiten zum Ablegen von JavaDatentypen und –Klassen als SQL-Datentyp Kai Jannaschk || [email protected] 03.06.2008 Aufbau Kai Jannaschk || [email protected] 03.06.2008 Beispiel // Erzeugen der Connection via JDBC // Connection con = DriverManager.getConnection(…); // Iterator #sql iterator StudentenItr (String name, String matrikel); StudentenItr studentenItr; // Anfrage deklarieren String matr = „81%“; #sql studentenItr = {SELECT * FROM Studenten WHERE matrikel like :matr}; while (studentenItr.next()) System.out.println(studentenItr.name()); studentenItr.close(); Kai Jannaschk || [email protected] 03.06.2008 Vergleich zu JDBC Vorteile: Vorkompilierung der Statements Überprüfung vor Programmlaufzeit Parameterbinding einfach, da direkter Zugriff auf HOSTVariablen, Funktionen, … Performanz der Abfrage, da Ausführungsplanerstellung bereits zur Kompilierung Nachteile: SQLJ-Programm muss erst in Java-Programm transformiert werden Aufwändigere Entwicklung Schema muss am Anfang eindeutig feststehen Kai Jannaschk || [email protected] 03.06.2008 O/R-Mapping Was ist das? Warum? Wie? Kai Jannaschk || [email protected] 03.06.2008 Idee Kopplung von objektorientierter PS und relationaler DB Füge zwischen Anwendung und RDBMS eine zusätzliche Softwareschicht ein, die das O/R-Mapping automatisch und transparent durchführt Kai Jannaschk || [email protected] 03.06.2008 O/R-Mismatch unterschiedliche Paradigmen OO: Identität, Zustand, Verhalten, Kapselung von Eigenschaften, Pointer ER: relationale Algebra (Tabellen, Schlüssel) Objektidentität (Identifizierung, Gleichheit) und Objektlebenszyklus (transient vs. persistent) Kai Jannaschk || [email protected] 03.06.2008 Probleme des O/R-Mapping Das OO Modell enthält reichere Strukturierungsmechanismen als das relationale Modell. Die folgenden Konzepte müssen transformiert werden: Klassen Aggregation Assoziationen Komposition Vererbung Objektidentität (OO vs. ER) und Objektlebenszyklus (transient vs. persistent) Kai Jannaschk || [email protected] 03.06.2008 Umsetzung Einfaches Bsp.: eine Klasse für Tabelle + ein Klassenattribut je Tabellenspalte => ein Tupel der Tabelle entspricht einer konkreten Klasseninstanz Fremdschlüssel in Relationen werden zu Objektassoziationen Problem des „Lazy Loadings“ Kai Jannaschk || [email protected] 03.06.2008 Hibernate Kai Jannaschk || [email protected] 03.06.2008 Aufbau von Hibernate Kai Jannaschk || [email protected] 03.06.2008 Objektlebenszyklus Kai Jannaschk || [email protected] 03.06.2008 Von der Tab zum POJO <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN“ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="hib.Vorlesung" table="VORLESUNG" schema="VL"> <id name="vlnr" type="java.lang.String"> <column name="VLNR" length="10" /> <generator class="assigned" /> </id> <property name="name" type="java.lang.String"> <column name="NAME" length="40" not-null="true" /> </property> <property name="stunden" type="java.lang.Long"> <column name="STUNDEN" precision="22" scale="0" not-null="true" /> </property> </class> </hibernate-mapping> Von der Tab zum POJO public class Vorlesung implements java.io.Serializable { private static final long serialVersionUID = -433311394853267882L; private String vlnr; private String name; private Long stunden; /** default constructor */ protected Vorlesung() { } /** minimal constructor */ public Vorlesung(String vlnr, String name, Long stunden) { this.vlnr = vlnr; this.name = name; this.stunden = stunden; } // Property accessors public String getVlnr() { return this.vlnr; } protected void setVlnr(String vlnr) { this.vlnr = vlnr; } // … } ID-Generatoren Dienen der Schlüsselerzeugung und damit zur Bestimmung der Objektidentität in OO bzw. ER <id name="id" type="long" column="cat_id"> <generator class="org.hibernate.id.TableHiLoGenerator"> <param name="table">uid_table</param> <param name="column">next_hi_value_column</param> </generator> </id> Generatoren: increment, identity, sequence, hilo, uuid, assigned, select, foreign Vererbung: Tab je Klassenhierarchie 1 Tabelle für alle Subklassen <class name="Payment" table="PAYMENT“> <id name="id" type="long" column="PAYMENT_ID“> <generator class="native"/> </id> <discriminator column="PAYMENT_TYPE" type="string"/> <property name="amount" column="AMOUNT"/> … <subclass name="CreditCardPayment" discriminatorvalue="CREDIT“> … </subclass> </class> Spalten in der Tab der Subklassen dürfen keinen NOT NULL-Constraint besitzen! Kai Jannaschk || [email protected] 03.06.2008 Vererbung: Tab je Subklasse Jede Subklasse eigene Tabelle + eigene Tabelle der Superklasse <class name="Payment" table="PAYMENT“> <id name="id" type="long" column="PAYMENT_ID“> <generator class="native"/> </id> <property name="amount" column="AMOUNT"/> … <joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT“> <key column="PAYMENT_ID"/> … </joined-subclass> </class> Primärschlüssel der abhängigen Tabs sind gleichzeitig Fremdschlüssel auf Superklasse Superklasse implementiert als Abstract Class Entspricht XOR von (H)ERM Kai Jannaschk || [email protected] 03.06.2008 Vererbung: Tab je konkreter Klasse Jede Subklasse als eigene Klasse <class name="CreditCardPayment" table="CREDIT_PAYMENT“> <id name="id" type="long" column="CREDIT_PAYMENT_ID“> <generator class="native"/> </id> <property name="amount" column="CREDIT_AMOUNT"/> … </class> Eigenschaften der Superklasse in jeder Subklasse Superklasse ist Interface Kai Jannaschk || [email protected] 03.06.2008 Collections Unterstützung der Persistierung von Map, Set, SortedMap, SortedSet, List List benötigt ein spezielles Sortierattribut (index) Speichern von neuen Objekten in assoziierten Collections mit Speicherung des Eigner-Objektes mgl. Bidirektionale Assoziation vs. Unidirektionale Assoziation Kai Jannaschk || [email protected] 03.06.2008 Abfragesprachen HQL Ähnlich SQL Objektorientierte Abfragesprache Criteria Query Abfrage weniger mächtig als HQL Dynamische Entwicklung von Abfragen (keine einfache Stringmanipulation) Geringe Unterstützung von Projektion u. Aggregation SQL (Migrationsmöglichkeit) Kai Jannaschk || [email protected] 03.06.2008 Anforderungen Die Hibernate-Bibliothek Hibernate-Config-File Mapping entweder per eigener xml-Datei oder per Annotation in Java-Klasse Klassen sind serialisierbar Jede zu persistierende Klasse benötigt einen DefaultKonstruktor Für jedes Klassenattribut muss es entsprechende set() + get() bzw. is()-Methoden geben Kai Jannaschk || [email protected] 03.06.2008 Probleme und Gefahren Schlechte Unterstützung von zusammengesetzten Schlüsseln in Hibernate Hoher Einmalaufwand zur Erstellung der ganzen Umgebung (Mapping, POJOs, DAOs) Wo modelliere ich die Integritätsbedingungen, und überwache sie? OO-Design beeinflusst ER-Modellierung SQL-Abfragen werden implementiert (all-Quantor) Quellen www.hibernate.org „Hibernate in Action“ CHRISTIAN BAUER, GAVIN KING ISBN 1932394-15-X Natürlich viele weitere Quellen im www Kai Jannaschk || [email protected] 03.06.2008