# Pattern für Datenbank Anwendung



## Gast (19. Nov 2007)

Hallo,

ich erstelle gerade eine Anwendung mit einer DB und frage mich, welche Pattern sich hierbei besonders gut einsetzen
lassen. Es sollen Daten gespeichert, verändert , gesichtet und gelöscht werden können.


Ich habe mir überlegt, dass man hierbei möglicherweise das Strategie Pattern einsetzen könnte.
Ich habe eine Strategie Klasse mit 4 Unterklassen:

Klasse A : SELECT
Klasse B : UPDATE
Klasse C : DELETE 
Klasse D : INSERT

--------------------

Ist das eine Möglichkeit ? Über Meinungen und Hinweise wäre ich dankbar.
Gibt es bei DB Anwendungen andere Pattern, die besonders gut geeignet wären ?


Vielen Dank  


VG


----------



## Niki (19. Nov 2007)

Normalerweise wenn du eine Persistenzschicht verwendest hast du für jede Tabelle min. 2 Klassen:
ein DAO = Data Access Object, dieses Object dient zum Zugriff (also insert/update/delete/select)
ein POJO = Plain Old Java Object, das ist ein reiner Datenhalter, ohne Logik. Ein Objekt stellt einen Datensatz dar

die DAOs bekommen über Methoden die POJOs und wissen wie sie dieses Speichern sollen

Dafür gibt es aber einige Frameworks: hibernate, toplink, torque,...


----------



## maki (19. Nov 2007)

Exemplarisches DAO:
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html



> Dafür gibt es aber einige Frameworks: hibernate, toplink, torque,...


und iBatis


----------



## Gast (19. Nov 2007)

Hallo, danke für Deine schnelle Antwort. Frameworks kommen leider nicht in Frage. Es ist ein Schulprojekt bei dem mögl. viele Pattern zum Einsatz kommen sollen.

Ich habe bisher für jeden Tabelle eine Klasse, die jeweis für die 
DB Felder setter und getter Methoden bereit hält.
Das wäre wohl dann die POJO

Jetzt bin ich auf der Suche nach der besten Lösung zur Kommunikation mit der DB , welche am Besten mit Hilfe eines 
pattern zum Tragen kommt. 

Daher auch meine Überlegung bez. des Strategie Pattern.

Hast du vielleicht einen Tipp oder einen Link ??

VG


----------



## maki (19. Nov 2007)

Das Strategy Pattern ist da wohl daneben bzw. zu fein granular.
Das allgemein "richtige" Pattern ist das DAO Pattern, musst dich halt reinlesen.

Eine DAO Schicht selbst zu schreiben ist nicht aufwendig, den link hab ich dir bereits gegeben.
Im DAO Pattern stecken viele kleinere Pattern drin


----------



## Gast (19. Nov 2007)

Ja, hab schon gesehen. Tausend Dank . Hab Dein Post erst nach meinem gesehen. Echt Spitze . meine Lektüre für heute Abend )


----------



## Gast (20. Nov 2007)

OK. Nur noch einmal zu Verständnis.  Ich habe 4 Komponenten:

Business Objekt
Transfer Objekt
Data Source
Data Access Object

Data Source ist meine Datenbank.

Transfer Objekte sind die Klasse wo die Daten abgelegt werden, mit den getter und setter Methoden

DAO sin die Klassen, die die direkten Anweisungen für die DB enthalten und auch als fabrik
implementiert werden können.


Business Objekt:  Ist das mein Controller ?  Wenn ich MVC einsetze , müßten die Business Objekte
doch meinem Controller entsprechen ?


Viele Grüße


----------



## maki (20. Nov 2007)

Transfer Objekte sind out, du benutzt stattdessen deine POJOs, mittlerweile auch  Domain Objekte genannt.

Auch wirst du keine EJBs einsetzen (Business Objekt), sondern wirst wahrscheinlich in einer Art "Controller" aus deinem MVC Framework (?) die DAOFactory aufrufen, welche dir die DAOs erzeugt.
DataSource ist übrigens ein Interface aus java.sql.


----------



## Gast (21. Nov 2007)

Hey, vielen Dank maki.

Zitat:
DataSource ist übrigens ein Interface aus java.sql.


Ich habe schon einen eigenen Datenbankcontroller , der die Verbindungen zur Datenbank regelt.
Ich wollte es dann so machen , dass alle DAO 'S von deiser Klasse erben. Dort 
sind Methoden wie getConnction() und loadJDBCTreiber() enthalten.

Das kommt der Interface Geschichte doch schon sehr Nahe. Geht wohl auch oder ?


Also habe ich dann für jede Tabelle eine DAO und eine einzige Fabrik-Klasse, die mir meine
DaoObjekte erzeugt. 

In den Dao's selbst liegen dann jeweils 4 Methoden, die SELECT / INSERT / UPDATE / DELETE
abdecken.


VG


----------



## Niki (21. Nov 2007)

Jo schaut recht gut aus. Was ich gerne mache ist einen Connection Pool verwenden. Wenn es sich um eine Client Anwendung mit nur einer Verbindung handelt ist das aber hinfällig. Der Pool wird einmal beim Starten der Applikation initialisiert (mittels setup, beinhaltet treiber, url, user, pwd, anzahl verbindungen, automatisches erstellen von Verbindungen falls keine vorhanden sind).
Der Code würde dann so aussehn:

```
DBConnection dbcon = null;
		try {
			dbcon = DBConnectionPool.getInstance().getConnection();
			USERDAO<USER> dao = DAOFactory
					.getUSERDAO(dbcon);
			for (USER u : userList) {
				dao.insert(u);
			}
			dbcon.commit();
		} catch (Exception ex) {
			Settings.LOGGER.error("Beim Speichern ist ein Fehler aufgetreten", ex);			
		} finally {
			DBConnectionPool.getInstance().releaseConnection(dbcon);
		}
```


----------



## ARadauer (21. Nov 2007)

> In den Dao's selbst liegen dann jeweils 4 Methoden, die SELECT / INSERT / UPDATE / DELETE


ja so ungefähr, man kann schon einwenig flexible sein.

zb für User

public User readUser(int userId);
public ArrayList<User> readAllUser();
public void deleteUser(int userId);
....

was du halt brauchst.



> Business Objekt: Ist das mein Controller ? Wenn ich MVC einsetze , müßten die Business Objekte
> doch meinem Controller entsprechen ?


Ich instanziere mir meine DAOs immer im Model, (Benutzer klickt auf laden->Commando an Controller -> Controller weißt Model an die Daten zu laden ->Model lädt mittels DAO die Daten -> Model informiert über ObserverPattern die Views über das Ergebnis
Aber ich denk darüber kann man streiten, gibt sicher viele die das im Controller machen.



> Transfer Objekte sind out, du benutzt stattdessen deine POJOs, mittlerweile auch Domain Objekte genannt.


 eh alles das selbe oder?


----------



## Guest (22. Nov 2007)

> ja so ungefähr, man kann schon einwenig flexible sein.
> 
> zb für User
> 
> ...



Alles klar, ich mache mir eben unterschiedliche DAOs . Doch wenn ich unerschiedliche DAOs habe, muss ich
ja für jede Klasse eine Factory zur Verfügung stellen, die dann immer exakt das selbe Objekt erzeugt?

Für meine Klasse Beitäge habe ich ja ganz andere Methoden. 

Die Factory hätten dann nur 1Methode   erstelleUserDAO()   oder erstelleBeitragDAO()
und die DAO Objekte erben von der Factory ?!

VG


----------



## ARadauer (22. Nov 2007)

ich persönlich mach das ohne Factory

UserDao userDao = new UserDao();
User franzl = userDao.getUser(5);

bin mir jetzt nicht sicher, welchen vorteil mir eine factory bringen würde, aber ich bin auch nicht der pattern guru.


----------



## maki (22. Nov 2007)

> bin mir jetzt nicht sicher, welchen vorteil mir eine factory bringen würde


Du müsstest nicht mehr wissen, das es sich um eine UserDao Klasse handelt 

Du würdest entweder eine Methode der DAO Factory aufrufen (getUserDao), oder die User Klasse als Paramter an eine Factorymethode übergeben.
Die Connection und andere Details sollten alle von der Factory verwaltet werden, du brauchst in deinem Code nicht zu Wissen, ob JDBC oder irgendetwas anderes verwendet wird.
Schliesslich werden solle Details von der Factory abstrahiert.


----------



## Gast (22. Nov 2007)

Super, vielen Dank...

maki, wenn ich Dich jetzt richtig verstehe brauche ich doch nur eine Factory Klasse für alle DAOs.

Also entweder eine Klasse  "Fabrik" , die für jede DAO eine eigene Methode hat.

oder für jede DAO eine eigene Fabrik ? 

Hab mir das gerade hier mal angeschaut:

http://www.theserverside.de/factory-method-pattern-in-java/

In den Beispiel werden halt nur Autos erzeugt. ich habe ja Objekte
mit verschiedenen Inhalten.

Würde das Pattern sehr gerne verwenden...

VG


----------



## maki (22. Nov 2007)

Eine Factory für alle DAOs einer Datenbank.

Am einfachsten wäre es, eine Methode pro DAO anzubieten, zB getUserDao(), getDocumentDao(), etc. pp.

Fortgeschrittene Implementierungen lassen wir mal aussen vor


----------



## Gast (22. Nov 2007)

Yes , tausned Dank ...


----------



## maki (22. Nov 2007)

Alle DAOs sollte ein gemeinsames Interface haben(Implementieren), welche die Operationen ( find(..), save(..), update(..), delete(..), etc. pp. )bereitstellt.
Dao eignet sich gut als Interface name 

Der Rückgabewert der getUserDao() und aller anderen Factory Methoden sollte dieses Interface sein, welche konkrete Implementierung (Klasse) es nun ist, ist allein Sache der Factory(methode).


----------



## *Hendrik (22. Nov 2007)

Hier mal ein Hibernate Beispiel zum Thema DAO. (Der Hibernate-spezifische Code lässt sich ja austauschen.)


----------



## Gast (22. Nov 2007)

Hallo, wenn ich nun meine Methoden in den DAO's sehr feingranular setze und jede DAO andere Methoden hat, dann habe ich sehr viele leere Methoden, da ich zwangsläufig alle implementieren muss.


```
public interface Dao {
	
	public void saveUser(String name);
	public void updateUser(int userID, String name);
	public void deleteUser(int userID);
	public String findUser(int userID);

}
```


```
public class userDao implements Dao{
	public void saveUser(String name) {}
	public void updateUser(int userID, String name) {}
	public void deleteUser(int userID) {}
	public String findUser(int userID) { return "Hallo"; }
}
```


```
import my.utils.DBController;

public class DaoFactory extends DBController {
	
	public Dao getUserDao() {
		Dao userDao = new userDao();
		return userDao;
	}

}
```

Das Interface macht gerade bei MVC schon Sinn. Würde dann in der GUI die Factory aufrufen . Ist das korrekt ?


----------



## maki (22. Nov 2007)

> Hallo, wenn ich nun meine Methoden in den DAO's sehr feingranular setze und jede DAO andere Methoden hat, dann habe ich sehr viele leere Methoden, da ich zwangsläufig alle implementieren muss.


Versuch doch mal die Methoden im Interface sehr generell zu halten, zB save, delete, etc. anstatt saveUser, deleteUser...
Natürlich kannst auch jedes Entität sein eigenes Dao Interface verpassen.
Was du auf keinen Fall machen solltest ist alle feingranularen Methoden (saveUser, saveDocument, etc.) in ein einzigees Interface zu quetschen.

Eine abstrakte Klasse zu schreiben die das Interface implementiert kann helfen weniger redundanten Code zu schreiben: Implementiere alle Methoden des Interfaces, selbst wenn die Implementierung nix anderes macht als eine (UnsupportedOperation)Exception zu werfen, ist das schon viel wert 



> Das Interface macht gerade bei MVC schon Sinn. Würde dann in der GUI die Factory aufrufen . Ist das korrekt ?


Aus dem Controller bzw. aus einer EJB werden DAOs aufgerufen und ja, es ergibt sehr viel Sinn MVC und DAO zu verwenden, auch wenn die beiden nicht immer direkt etwas miteinander zu tun haben, oft ist noch eine Schicht dazwischen (EJB).


----------



## Gast (24. Nov 2007)

Prima, das ist ja alles schon recht einleuchtend. Ist es richtig, dass ich einen Observer nicht zwangsläufig 
benötie ?  Ich meine, dass ich bei mir keinen benötige, glaube aber, dass der doch immer bei MVC
eingestezt wird. 

Habe ja jetzt meine Factory so in der Art:


```
public class DaoFactory {
	
	public Dao getUserDao() {
		DaoInterface  userDao = new userDao();
		return userDao;
	}
```

Diese wird dann im Contoller instantiiert. Habe also für jede DAO eine Methode wie oben.

Könnte ich denn nicht auch den Code so schreiben mit einer Methode , ähnlich wie in dem Link
von Henrik:


```
public static DAOFactory instance (Class factory)
{

try {
      return (DAOFactory) factory.newInstance();
      }catch (  Exception ex ) {
       throw new RuntimeException("Konnte keine Factory erzeugen : "+ factory  );
     }

}
```


Ich instantiiere ja eigentlich über das Interface . Da kann ich ja oben keine direkte Klasse eintragen.



VG


----------



## *Hendrik (24. Nov 2007)

Kommt darauf an, ob Du nur eine konkrete Factory verwenden möchtest. 
Das Hibernate Beispiel zeigt eine Implementierung mit Hibernate, d.h. Du hast eine konkrete HibernateFactory, die HibernateDAOs instanziert. Durch die Verwendung der abstrakten DAOFactory im Controller, kannst Du den kompletten Datenbankzugriff durch Implementierung einer anderen konkreten Factory einfach ändern. Willst Du irgendwann mal eine andere Factory verwenden, dann wäre die Nutzung einer abstrakten Factory sinnvoll.


----------

