eCommerce JDBC Anbindung

Werbung
e-Commerce
Datenbankanbindung mit JDBC
Prof. Dr. Nikolaus Wulff
Persistente Objekte
• Objekte belegen einen bestimmten Speicherplatz
und existieren eine gewisse Zeit lang während der
Programmausführung.
• Definition:
– Persistenz speichert den Status und die Klasse eines
Objektes durch Zeit und Raum.
• Aufgabe eines Datenbanksystems ist es die
Persistenz der Objekte zu gewährleisten, ohne das
sich der Anwendungscode von dem transienter
Objekte unterscheidet.
Prof. Dr. Nikolaus Wulff
e-Commerce
2
Objekte und Klassen
• Objekte
– haben eine eindeutige Identität (OID)
– haben einen Status = Σ Attribute
– haben ein Verhalten = Σ Methoden
• Klassen
– eine Klasse ist eine Menge von Objekten mit
• einer gemeinsamen Struktur und
• einem gemeinsamen Verhalten
Prof. Dr. Nikolaus Wulff
e-Commerce
3
Objekte und Klassen (I)
P e rs o n
Klasse:
Objekt:
n a m e : S trin g
vo rn a m e : S trin g
Statische Struktur
w o h n s itz : Ad re s s e
a lte r : in t
Instanzen der Klasse
niko:Person
name
Prof. Dr. Nikolaus Wulff
= Wulff
erwin:Person
name
= Müller
vorname = Nikolaus
vorname = Erwin
wohnsitz= Lübeck
wohnsitz= Hamburg
alter
alter
= 39
e-Commerce
= 45
4
Objekte und Klassen (II)
Überführung des statischen OO-Modells in ein ER-Modell
OO-Modell
ER-Modell
•
•
•
•
•
•
Klasse
Instanz
Attribut
Prof. Dr. Nikolaus Wulff
e-Commerce
Tabelle
Zeile
Feld
5
Objekte und Klassen (III)
• Verwaltung der ObjektID
• Abbildung von Beziehungen
– Abbildung von Vererbungsbeziehungen
• Klassen erben die Attribute der Super-Klasse
• Dynamisches Binden, Zugriff über die Super-Klasse
– Assoziationen und Aggregation
• Assoziation als Fremdschlüssel
• Automatisches Nachladen von aggregierten Klassen
• Objekt/Instanz - Abbildung
– Abbildung der Attribute
• Mapping => Zuordnen der Tabelle und Felder
• Casting => Überführen auf Datentypen des RDBMS
Prof. Dr. Nikolaus Wulff
e-Commerce
6
Objekte und Klassen
Objekt:
niko:Person
name
= Wulff
name
= Müller
vorname = Nikolaus
vorname = Erwin
wohnsitz= Lübeck
wohnsitz= Hamburg
alter
alter
Tabelle:
OID name
Xyz3450 Wulff
uvq4711 Müller
...
Prof. Dr. Nikolaus Wulff
erwin:Person
= 39
= 45
vorname
wohnsitz
alter
Nikolaus
Lübeck, ...
39
Erwin
Hamburg
45
...
...
...
e-Commerce
7
ObjektID und Primärschlüssel
Ist das Konzept des Primärschlüssels identisch zur ObjektID?
ObjektID
• ist eindeutig
• unveränderlich
• strukturlos
Primärschlüssel
• eindeutig pro Tabelle
• kann sich ändern
• je nach Tabelle anders
• Der (fachliche) Primärschlüssel eignet sich nicht als OID.
• Modellierung der OID als getrennte Klasse, mit
• extra Spalte im ER-Modell (Forward-Engineering)
• oder abgeleitet aus Tabelle und Primär-Schlüssel
(Reverse-Engineering)
Prof. Dr. Nikolaus Wulff
e-Commerce
8
Klassendiagramm
P e rso n
F irm a
nam e : S tring
adres s e : A dres s e
b e sch ä ftig t
1
1..*
V e rtra g
pos ition : S tring
gehalt : float
Prof.
Dr.
Nikolaus
Wulff
Prof.
Dr.
Nikolaus
Wulff
e-Commerce
name : S tr ing
vorn ame : S tr ing
woh ns itz : A dres s e
alter : int
ER-Diagram
Tabelle:
Firma
Vertrag
1:N
Person
1:1
• Objekt Modell
• ER- oder Tabellenmodell
• SQL Code
Zeitliche
Entwicklung
im Projekt
CREATE TABLE Person
person-id
ID not null,
vertrag-id
ID not null,
PRIMARY KEY (person-id),
FOREIGN KEY (vertrag-id) REFRENCES Vertrag
Prof.
Dr.
Nikolaus
Wulff
Prof.
Dr.
Nikolaus
Wulff
e-Commerce
OO- und ER-Modell Koppelung
• „SQL-Objekt“
– sehr enge Koppelung
– Objekte beinhalten SQL-Code
• Abstrakte DB-Superklasse
– enge Koppelung
– Jede Klasse kennt seine Tabelle
– OO-Modell stark vom ER-Modell abhängig
• Persistenzmodell
– lose Koppelung => Schichtenarchitektur
– BO-Klassen wissen nichts um ihre Persistenz
Prof. Dr. Nikolaus Wulff
e-Commerce
11
Schichtenarchitektur
OO-Modell
P e rso n
ER-Modell
L o a d e rP e rso n
Person
1 ..*
b e sch ä ftig t
L o a d e rV e r tra g
1
F irm a
Prof. Dr. Nikolaus Wulff
L o a d e rF irm a
e-Commerce
Vertrag
Firma
12
Persistenz - Framework
DB - Klassen
1
< < d a ta b a se > >
DBL o a d e r
0..*
S m a rtPo i n te r
O ID
1
1
O IDP e rso n
O IDF irm a
L o a d e rP e rso n
L o a d e rF irm a
Helper-Klassen
< < p ro x y> >
S P F irm a
F irm a
1
0..1
< < p ro x y> >
S P P e rso n
1..*
P e rso n
1
Prof. Dr. Nikolaus Wulff
1
Business-Klassen
1
1..*
b e sch ä ftig t
0..1
e-Commerce
13
JDBC Kernidee
• Die Java DataBase Connectivity (JDBC) ist eine
Abstraktionsschicht für relationale Datenbanken.
• JDBC definiert einen Satz von Schnittstellen, die
von entsprechenden Datenbankherstellern mit
entsprechenden Treibern implementiert werden.
• Dem Java Entwickler präsentiert sich immer die
selbe SQL konforme Schnittstelle, unabhängig
von der verwendeten Datenbank.
• Somit lassen sich Anwendungen für
verschiedenen Datenbanken wie DB2, Oracle,
mySQL usw. vollkommen transparent
programmieren.
Prof. Dr. Nikolaus Wulff
e-Commerce
14
JDBC Architektur
Abstract Factory
package java.sql
DriverManager
Factory
SQLException
SQLWarning
MetaData
0..*
<<Interface>>
Driver
DriverPropertyInfo
0..*
<<create>>
<<Interface>>
Connection
<<Inter face>>
DatabaseMetaData
<<derived>>
<<create>>
Command
Iterator
<<Interface>>
Statement
<<creat e>>
<<Interface>>
ResultSet
<<derived>>
<<Inter face>>
ResultSetMetaData
<<Interface>>
PreparedStatement
Prof. Dr. Nikolaus Wulff
e-Commerce
15
Relational-Object-Mapping
• JDBC bietet keine echte objektorientierte
Abstraktion zur Persistenz von Business-Objekten.
• Objekte haben per se keine 1:1 Abbildung auf
relationale Datenbanken:
– das Schreiben muss per Hand codiert werden.
– der ResultSet enthält nur primitive Datentyen und die
Objekte müssen per Hand zusammengesetzt werden
• Diese Problem wird in der Literatur als
Impedanzmissmatch bezeichnet.
Prof. Dr. Nikolaus Wulff
e-Commerce
16
Java SQL Typkonvertierung
• = Konvertierung
empfohlen
x = Konvertierung
möglich
Identifizieren der
Spalte über Namen
oder Position.
Große Daten- oder
Textobjekte werden
über Streams
ausgelesen.
Prof. Dr. Nikolaus Wulff
e-Commerce
17
Einfaches Object Mapping
• Im einfachsten Fall wird jede Klasse auf eine
Tabelle abgebildet.
• Jede Instanz/Objekt der Klasse bildet eine Zeile
der Tabelle.
• Jedes Attribut wird genau auf eine Spalte
abgebildet. Dies setzt voraus, das es sich um einen
primitiven SQL Datentyp handelt. Ansonsten
muss ein Foreign Key verwaltet werden.
• Meist wird für die Objektidentität ein künstlicher
Primary Key vergeben.
Prof. Dr. Nikolaus Wulff
e-Commerce
18
Lesen einer Tabelle
client
driver : Driver
Manager
cont :
Connection
stm : Statement
r s : ResultSet
getConnection(String, String, String)
createStatement( )
executeQuery(String)
next( )
getObject(int)
// read Table
Resu ltSet rs = stm.executeQuery(where);
wh ile(rs.next()) {
for (int col=0; col<colums; col++) {
Ob ject co lum = rs.getObject(i);
.....
} // loop over columns
} // loop over ro ws
Prof. Dr. Nikolaus Wulff
e-Commerce
19
BookStore Test
TestCase
(from j unit.framew ork)
BookStoreTest
tests
-dri ver
BookStore
<<uses>>
find/store
<<Interface>>
Driver
(from j av a.sql)
<<creates>>
<<creates>>
<<Interface>>
Connection
Book
(from j av a.sql)
Book attributs map
to the ResultSet
<<creates>>
<<Interfac e>>
ResultSet
• Test mit JUnit.
• Typische zu testende Operationen sind:
(from j av a. sql)
–
–
–
–
<<creates>>
<<Interface>>
Statement
(from j av a.sql)
findAll
findByXXX
store per update oder insert
Löschen per delete
Prof. Dr. Nikolaus Wulff
e-Commerce
20
Testaufbau
public class BookStoreTest extends TestCase {
private
private
private
private
private
final static String DRIVER = "org.gjt.mm.mysql.Driver";
final static String DBURL = "jdbc:mysql://localhost/bookstore"
final static String USER = "bookstore";
final static String PWD = "bookstore";
BookStore bookstore;
Verwendet wird der MySQL
/**
Treiber für die bookstore Datenbank.
* @param arg0
URL, User und Passwort wie angegeben
*/
public BookStoreTest(String arg0) {
super(arg0);
}
/**
* Setup for the test.
*/
public void setUp() throws Exception {
bookstore = new BookStore(DRIVER, DBURL, USER, PWD);
}
Prof. Dr. Nikolaus Wulff
e-Commerce
21
Test von find und store
/**
* test the findAll method.
* @throws Exception
*/
public void testFindAll() throws Exception {
Collection result = bookstore.findAll();
assertTrue("result empty ", result.size() > 0);
}
/**
* test the insert operation.
* @throws Exception
*/
public void testInsert() throws Exception {
String isbn = (new Date()).toString();
Book book = new Book(isbn, "junit", getName(), "JUnit Test");
bookstore.store(book);
Collection result = bookstore.findByIsbn(isbn);
assertTrue("insert not found ", result.size() == 1);
}
Prof. Dr. Nikolaus Wulff
e-Commerce
22
BookStore Erzeugung
public class BookStore {
private final Driver driver;
private final String url;
private final String user;
private final String password;
/**
* Constructor to initialize the BookStore database connection.
*
* @param driverName
String classname of the JDBC driver
* @param url
String the url of the database
* @param user
String the user name of the database
* @param password
String the database password
* @throws Exception
any kind of exceptions to be thrown...
*/
public BookStore(String driverName, String url, String user,
String password) throws Exception {
Class clazz = Class.forName(driverName);
this.driver = (Driver) clazz.newInstance();
this.url = url;
this.user = user;
this.password = password;
}
Prof. Dr. Nikolaus Wulff
e-Commerce
23
Verbindung zur Datenbank
/**
* Returns a sql connection to the database.
*
* @return java.sql.Connection the connection to use
* @throws java.sql.SQLException in case of an error
*/
private Connection getConnection() throws SQLException {
Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", password);
return driver.connect(url, props);
}
• Die Verbindung zur Datenbank wird für autorisierte
User mit entsprechendem Paßwort erzeugt.
• Im Fehlerfall wird eine SQLException geworfen.
• Die Ressourcen müssen nach dem Gebrauch per
close Befehl wieder freigegeben werden.
Prof. Dr. Nikolaus Wulff
e-Commerce
24
Resourcenfreigabe
private void releaseResources(Connection con,
Statement stm, ResultSet rs) {
try {
if (rs != null)
rs.close();
} catch (Exception e) {
handleError(e);
}
try {
if (stm != null)
stm.close();
} catch (Exception e) {
handleError(e);
}
try {
if (con != null)
con.close();
} catch (Exception e) {
handleError(e);
}
}
Prof. Dr. Nikolaus Wulff
e-Commerce
25
Generische Suche
public Collection findByAuthor(String author) {
String where = " where author='" + author + "'";
return find(where);
}
public Collection findByIsbn(String isbn) {
String where = " where isbn='" + isbn + "'";
return find(where);
}
public Collection findByTitle(String title) {
String where = " where title='" + title + "'";
return find(where);
}
Alle Suchoperationen verzweigen auf
public Collection findAll() { die interne, generische find Operation.
return find("");
}
Zurückgegeben wird eine Collection
gefüllt mit Büchern.
Prof. Dr. Nikolaus Wulff
e-Commerce
26
Die generische Suchroutine
private Collection find(String where) {
ResultSet set = null; Statement stm = null; Connection con = null;
ArrayList bookList = new ArrayList();
String sql = "select * from books " + where;
try {
con = getConnection();
stm = con.createStatement();
set = stm.executeQuery(sql);
while (set.next()) {
long id = set.getLong("id");
String isbn = set.getString("isbn");
String author = set.getString("author");
String title = set.getString("title");
String description = set.getString("description");
bookList .add(new Book(id, isbn, author, title, description));
}
} catch (SQLException e) {
handleError(e);
} finally {
releaseResources(con, stm, set);
}
return bookList ;
}
Prof. Dr. Nikolaus Wulff
e-Commerce
27
Generisches Speichern
public void store(Book book) {
if (findById(book.id.longValue()).size() == 0) {
insert(book);
} else {
update(book);
}
}
• Je nach dem ob das Buch schon in der Datenbank
vorhanden ist oder nicht muss unterschiedlich
vorgegangen werden:
– Buch ist neu => Insert Statement
– Buch ist alt => Update Statement
Prof. Dr. Nikolaus Wulff
e-Commerce
28
Speichern per Insert
private void insert(Book book) {
StringBuffer sql = new StringBuffer("insert into books ");
sql.append("(isbn,author,title,description) ");
sql.append(" values(");
sql.append("'");
sql.append(book.isbn);
sql.append("',");
sql.append("'");
sql.append(book.author);
insert und update Methoden erzeugen
sql.append("',");
ein Kommando, das an die executeSQL
sql.append("'");
Methode übergeben & ausgeführt wird.
sql.append(book.title);
sql.append("',");
sql.append("'");
sql.append(book.description);
sql.append("'");
sql.append(")");
// forward the sql string to the executeSQL method
executeSQL(sql.toString());
Prof.}
Dr. Nikolaus Wulff
e-Commerce
29
Speichern per Update
private void update(Book book) {
StringBuffer sql = new StringBuffer("update books ");
sql.append(" set isbn='");
sql.append(book.isbn);
sql.append("', author='");
sql.append(book.author);
sql.append("', title='");
sql.append(book.title);
sql.append("', description='");
sql.append(book.description);
sql.append("' where id=");
sql.append(book.id);
// forward the sql string to the executeSQL method
executeSQL(sql.toString());
}
insert und update Methoden erzeugen
ein Kommando, das an die executeSQL
Methode übergeben & ausgeführt wird.
Prof. Dr. Nikolaus Wulff
e-Commerce
30
Persistenz per Mapper
• Der Bookstore dient als Fassade und beinhaltet die
Logik zum Speichern/Laden der Business-Objekte.
• Für einfache Anwendungen ist dies ausreichend,
belastet jedoch bei vielen verschiedenen Objekten
den Bookstore mit zu viel JDBC Code und
Detailwissen über die innere Struktur der Klassen.
• Abhilfe: Einführen einer Persistenzabstraktion.
• Einfachste Version: Strategie-Muster
Der Bookstore verwaltet eine Map mit zu den
Business-Objekten passenden Persistenz-Mappern,
an die entsprechende DB Befehle delegiert werden.
Prof. Dr. Nikolaus Wulff
e-Commerce
Persistenz Framework
• Datenbank Funktionalität in spezielle Mapper
Klassen auslagern.
• Einfachste Version:
– Alle BusinessObjekte erben von einer PersistenzKlasse.
– Alle Mapper erben von einem PersistenzMapper.
– Lediglich einige spezielle Methoden müssen überladen
werden.
• Vorteil:
– Modulare Mapper, einfache Implementierung
• Nachteil:
– Kopplung der BO-Klassen an PersistenzKlasse
Prof. Dr. Nikolaus Wulff
e-Commerce
Java Templates
• Der BookStore verwaltet eine Map mit zu den
Business Objekten passenden Mappern.
• Mit Hilfe von Java Generics läßt sich ein solcher
Persistenz Mechanismus als Template typsicher
implementieren.
• Ein PersistenzMapper wird als abstraktes Generic
definiert, dem nur noch einige spezialisierte
Mapping Funktionen fehlen, die in abgeleiteten
Klassen implementiert werden.
Prof. Dr. Nikolaus Wulff
e-Commerce
BookStore Mapper Verwaltung
• Der BookStore delegiert alle DB Aktionen an generische
Mapper Instanzen vom Typ <T>.
• Als Schlüssel dient die Class<T> Instanz des Objekts T.
BookStore
store(obj : PersistentObject) : void
delete(obj : PersistentObject) : void
type : Class<T>
Map
1
<T extends
PersistentObject>
PersistentMapper
store(obj : T) : void
delete(obj : T) : void
Prof. Dr. Nikolaus Wulff
mapps
e-Commerce
PersistentObject
PersistentMapper Template
<T extends PersistentObject>
<<abstract>>
PersistentMapper
table : St ring
scheme : S tring
type : Clas s<T>
connect ion : java. sql.Connect ion
Persis tent Object
id : long = -1
PersistentMapper(type : Class<T>, t able : S tring, schem e : St ring)
<<abstract>> insert (obj : T) : void
<<abstract>> updat e(obj : T) : void
<<abstract>> mappToInstance(set : Result Set) : T
isNew(obj : T) : boolean
setId(obj : T) : void
store(obj : T) : void
delete(obj : T) : void
execut eQuery(where : String) : Collection<T>
execut eSQL(sql : S tring) : void
PersistentMapper<Book>
Persistent Mapper<User>
getId()
setId()
PersistentMapper<Order>
BookMapper
insert(obj : Book) : void
update(obj : Book ) : void
mappToIns tance() : Book
Book
UserMapper
User
insert(obj : User) : void
update(obj : User) : void
mappToInst ance() : User
OrderMapper
insert(obj : Order) : void
update(obj : Order) : void
mappToInst ance() : Order
Prof. Dr. Nikolaus Wulff
e-Commerce
Order
Adapter als Dekorierer
• Trennung von fachlicher und technischer Schnittstelle.
• Anstatt die Business-Objekte von einer PersistentObject
Superklasse abzuleiten kann das Adapter Muster zur
Entkoppelung verwendet werden.
• Ein Adapter dekoriert die fachlichen BO-Instanzen mit der
technischen Funktionalität des Persistenzframeworks.
• BO-Klassen enthalten selber keinen Hinweis auf
eventuelle Datenbank Aktionen.
• Java EJBs und OR Mapper folgen diesem Ansatz in
unterschiedlicher Ausprägung.
• Die wesentlichen Ideen lassen sich einfach codieren oder
noch besser per Annotations oder XDoclet generieren.
Prof. Dr. Nikolaus Wulff
e-Commerce
Klassen-Adapter als Dekorierer
Book
Fachliche Schnittstelle
Technische Schnittstelle
<<Interface>>
PersistentObject
<T>
PersistentMapper
markDirty()
setId()
getId()
PersistentMapper<Book>
BookMapper
Prof. Dr. Nikolaus Wulff
Persistent Book
e-Commerce
Objekt-Adapter als Dekorierer
<<Interface>>
Book
1
BookImpl
Fachliche Schnittstelle
Technische Schnittstelle
<T>
PersistentMapper
<<Int erface>>
PersistentObject
PersistentMapper<Book>
BookMapper
Prof. Dr. Nikolaus Wulff
PersistentBook
e-Commerce
Anwendung eines Mappers
• Unabhängig von der speziellen Realisierung der
Mapper gestaltet sich eine Anfrage recht einfach:
public Collection<Book> findBooksByTitle(
String title) {
PersistentMapper<Book> mapper;
String where = " WHERE title='" + title + "'";
try {
mapper = getMapper(Book.class);
return mapper.executeQuery(where);
} catch(SQLException e) {
handleError(e);
return null;
}
}
Prof. Dr. Nikolaus Wulff
e-Commerce
Herunterladen