# DAO Pattern / BO Konvertierung



## kama (4. Aug 2008)

Hallo,

ich habe mir Anhand der Anleitung und einiger anderer Quellen einen DAO zusammen gebaut....funktioniert auch wunderbar und ist auch sehr kurz und schön der Code....

Wenn ich ja nun eine Methode aus dem DAO aufrufe z.B. save(T entity), dann habe ich es ja mit einem Datenbank Objekt zu tun (habe ich bei mir TO's genannt)....

Diese TO's möchte ich aber nicht an die Anwendungsschicht weiterreichen, da zum Teil Felder enthalten sind, die ich in der Anwendungsschicht nicht brauche (Business Objects) bzw. nicht haben will und nicht haben darf....

Die Frage ist jetzt, wo findet die Umwandlung der TO's in BO's statt?

Im DAO? Das heißt liefert ein DAO Aufruf direkt die entsprechenden BO's (anstatt der TO's) zurück? 

```
XXDAO<XYZBO> dao = DAOFactory.getXYZ();
List<XYZBO> result = dao.get();
```
Fände ich nicht so gut, da ich dann meiner Meinung nach in der DAO Schicht Dinge mache, die da nicht hin gehören...abgesehen davon würde ich mir den Zugang zu den TO's versperren...

Ich tendiere derzeit dazu, dass ich eine zusätzliche "Schicht" zwischen Anwendungschicht und DAO lege und dort die Umwandlung vornehme....

Oder wäre ein "Kopier Konstruktor" eine sinnvolle Variante:

```
XYZBO bo = new XYZBO(xyzto);
```
oder

```
XYZTO to = new XYZTO(xyzbo);
```


Habt' Ihr dazu Verbesserungsvorschläge oder gibt es irgendwo Links dazu ? Ich habe bisher immer nur zum Thema DAO eine ganze Menge gefunden...

Vielen Dank im Voraus.
MfG
Karl Heinz Marbaise


----------



## byte (4. Aug 2008)

Deine Datenbank-Objekte heissen TOs? Das ist etwas ungewöhnlich. Der übliche Begriff wäre Entität. TO (Transfer Object) nennt man hingegen die von den Entitäten entkoppelten Objekte zum Weiterreichen vom Persistenz-Layer zum Client-Layer.

Guck Dir dazu mal das TO Pattern an: http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html


Das Thema ist im übrigen heiss diskutiert. Dank OR-Mapper wie Hibernate ist es heutzutage nicht mehr zwingend notwendig, Transfer Objekte zu erzeugen. Es ist durchaus möglich, die Business Objekte direkt zwischen den Layern hin- und herzureichen.


----------



## kama (4. Aug 2008)

Hallo,

zuerst einmal vielen Dank für die Rückmeldung...



			
				byto hat gesagt.:
			
		

> Deine Datenbank-Objekte heissen TOs? Das ist etwas ungewöhnlich. Der übliche Begriff wäre Entität. TO (Transfer Object) nennt man hingegen die von den Entitäten entkoppelten Objekte zum Weiterreichen vom Persistenz-Layer zum Client-Layer.


Ja, sehr guter Hinweise.....ist mir nachdem ich das Posting geschrieben habe auch aufgefallen....Ist ja mit Eclipse nicht wirklich ein Problem...werde ich ändern.......



			
				byto hat gesagt.:
			
		

> Guck Dir dazu mal das TO Pattern an: http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html


Hatte ich schon mal zwischen aber anscheinend habe ich das nicht gut genug bzw. lange genug angeschaut....



			
				byto hat gesagt.:
			
		

> Das Thema ist im übrigen heiss diskutiert. Dank OR-Mapper wie Hibernate ist es heutzutage nicht mehr zwingend notwendig, Transfer Objekte zu erzeugen. Es ist durchaus möglich, die Business Objekte direkt zwischen den Layern hin- und herzureichen.


Ja. Ich nutze auch Hibernate...aber ich habe nun mal die Notwendigkeit definitiv TO's (bzw. VO's) zu erzeugen...

Somit würde ich jetzt sagen, dass es nun warscheinlich so läuft:

```
XYZDAO dao = DAOFactory.getXYZ();
List<XYZBO> boListe = dao.get();
....
XYZBO xyzBO = ...
XYZTO xyzTO = xyzBO.getTO();
```
Und das TO kann ich dann in einer anderen Schicht verwenden....mit weniger und/oder anderen Attributen....

Hier stellen dann die BO's die Objekte dar, die via DAO in der DB abgelegt werden bzw. gelesen werden...

MfG
Karl Heinz Marbaise


----------



## byte (4. Aug 2008)

Sieht ordentlich aus.
Es ist eigentlich üblich, eine Service-Schicht zwischen den Client- und den Persistence-Layer (DAOs) zu legen. Die DAOs wissen nichts von irgendwelchen Transfer Objekten sondern kennen nur die persistenten Entitäten (Business Objekte). Die Service-Schicht benutzt die DAOs, um an die Entitäten zu kommen und verpackt sie schlussendlich in TOs, um diese an den Client weiter zu reichen.


----------



## kama (4. Aug 2008)

Hallo,



			
				byto hat gesagt.:
			
		

> Sieht ordentlich aus.


Dank Deiner Hilfe ....



			
				byto hat gesagt.:
			
		

> Es ist eigentlich üblich, eine Service-Schicht zwischen den Client- und den Persistence-Layer (DAOs) zu legen. Die DAOs wissen nichts von irgendwelchen Transfer Objekten sondern kennen nur die persistenten Entitäten (Business Objekte). Die Service-Schicht benutzt die DAOs, um an die Entitäten zu kommen und verpackt sie schlussendlich in TOs, um diese an den Client weiter zu reichen.



Damit würdest Du vorschlagen, dass wie folgt zu machen:

```
class ServiceLayerXYZ ..{
    XYZTO get(Id) {
        XYZDAO dao = DAOFactory.getXYZ();
        XYZBO bo = dao.get(Id);
        XYZTO to = new XYZTO();
        to.setXXXX(bo.getXXX());...
        ...
        return to;
   }

   void save(XYZTO to) {
        XYZBO bo = new XYZBO();
        bo.setXXX(to.getXXX());
        ....
        XYZDAO dao = DAOFactory.getXYZ();
        dao.save(bo);
   }
   ...
   ServiceLayerXYZ sl = new ServiceLayerXYZ();
   XYZTO to = sl.get(Id);
   ....

   XYZTO to1 = new XYZTO();
   to1.set...();
   sl.save(to1);
```
Anstatt in die BO's ".getTO()" bzw. in die TO's ".getBO()" zu implementieren?

Das sieht besser aus, da wie Du schon bemerkt hast, die BO's nichts von den TO's wissen brauchen...und umgekehrt...

Viel besser entkoppelt...


BTW: Gibt es eigentlich einen sinnvolle Namenskonvention für den ServiceLayer ?
MfG
Karl Heinz Marbaise


----------



## maki (4. Aug 2008)

Google mal nach "TransferObjectAssembler", sieh dir auch die nachteile davon an (Komplexität), wenn du es dann immer noch brauchst, ist es eben so.



> BTW: Gibt es eigentlich einen sinnvolle Namenskonvention für den ServiceLayer ?


Klar, zB. ...Service wie UserService, etc.

DAOs abstrahiere ich gerne zu sog. Repositories, da können auch DomainObjekte andere sduchen/speichern etc. ohne das es einen Bruch gibt in den Abstraktionsebenen (Domain = high level, DAO = low level, Repository = high level)


----------



## byte (4. Aug 2008)

kama hat gesagt.:
			
		

> BTW: Gibt es eigentlich einen sinnvolle Namenskonvention für den ServiceLayer ?



Bei mir heissen die Services einfach BlablubService (Interface) und BlablubServiceImpl (Implementierung). Die DAOs heissen NameDerEntitätDao (Interface) und NameDerEntitätDaoHibernate (Hibernate-Implementierung). Ich würde den Begriff "Layer" nicht in den Bezeichnungen verwenden. Layer ist ja nur eine abstrakte Bezeichnung für das "Big Picture" (z.B. im Pflichtenheft). 

My 2C.


----------



## kama (4. Aug 2008)

Hallo,

vielen dank für die Hilfe...



			
				maki hat gesagt.:
			
		

> Google mal nach "TransferObjectAssembler", sieh dir auch die nachteile davon an (Komplexität), wenn du es dann immer noch brauchst, ist es eben so.


Wenn ich das derzeit richtig überblicke, benötige ich den "TransferObjectAssembler" nicht, da es derzeit noch so ist, dass eine XYZService nur Objekte vom Type XYZ liefert und keinen Verbund von unterschiedlichen Objekten....Das würde bedeuten, dass mein Code-Beispiel so eine recht gute Entkopplung darstellt und derzeit auch Ausreichend ist....

Den "TransferObjectAssembler" benötige ich ja dann, wenn ich beispielsweise Daten aus Objekt ABC, DEF als ein Object vom Typ XYZ auf Client Seite benötige....



			
				maki hat gesagt.:
			
		

> DAOs abstrahiere ich gerne zu sog. Repositories, da können auch DomainObjekte andere sduchen/speichern etc. ohne das es einen Bruch gibt in den Abstraktionsebenen (Domain = high level, DAO = low level, Repository = high level)


Wie würde denn so ein Repository Interface aussehen ?
MfG
Karl Heinz Marbaise


----------



## byte (4. Aug 2008)

kama hat gesagt.:
			
		

> Den "TransferObjectAssembler" benötige ich ja dann, wenn ich beispielsweise Daten aus Objekt ABC, DEF als ein Object vom Typ XYZ auf Client Seite benötige....


So wie ich das sehe, ist der TransferObjectAssembler generell dafür da, TOs aus den BOs zu erzeugen. Meistens sind die TOs kein 1:1 Abbild des BOs, deswegen der Begriff "Assembler".
Sind die TOs eh nur ein 1:1 Abbild der BOs, dann wäre das TO ja quasi nur eine einfache Kopie des BO. Dann kann man sich gleich fragen, wozu man das TO überhaupt braucht.
Aber das Thema ist sowieso heiss diskutiert.


----------



## kama (4. Aug 2008)

Hallo,



			
				byto hat gesagt.:
			
		

> Bei mir heissen die Services einfach BlablubService (Interface) und BlablubServiceImpl (Implementierung). Die DAOs heissen NameDerEntitätDao (Interface) und NameDerEntitätDaoHibernate (Hibernate-Implementierung). Ich würde den Begriff "Layer" nicht in den Bezeichnungen verwenden. Layer ist ja nur eine abstrakte Bezeichnung für das "Big Picture" (z.B. im Pflichtenheft).


Ich habe den Service jetzt XYZService genannt.....das mit dem Interface scheint mir auch noch eine gute Idee zu sein....

XYZServcie, XYZServiceImpl, XYZDAO, XYZDAOHibernate etc. wären dann die Namen....

wobei bei mir, die Geschichte jetzt per Generics gelöst ist....


```
public class IdBase {
    Long getId() { }
    void setId(Long id) { ...}
}

public class XYZBO extends IdBase {
....
}

public interface IGenericDAO<T, I extends Serializable> {
  T get(I id);
  List<T> getByExample(T example, String[] exludeProperties);
  List<T> get();
  void remove(T item);
  void remove(I id);
  T save(T item);
}

public class HibernateDAO<T extends IdBase, ID extends Serializable> 
	implements IGenericDAO<T, ID> {
   ....
}

public class IdDAO<T extends IdBase> extends HibernateDAO<T, Long> {
	public List<T> get() {...}
	public T get(Long id) {...}
	public List<T> getByExample(T example, String[] excludeProperties) {...}
	public void remove(Long id) {...}
	public void remove(T entity) {...}
	public T save(T entity) {...}
}

public final class DAOFactory {
	public static IdDAO<XYZBO> getXYZ() { return new IdDAO<XYZBO>(XYZBO.class); }
....
}
```

So jetzt ist mir noch zwei Punkte nicht klar....


1. Das Interface des Service, muss doch, meiner Meinung nach, die gleichen Methoden liefern, wie 
    mein IdDAO ?

2. Bis dato ist es so, dass die BO's und die TO's ja gemeinsamkeiten haben.
    Die Attribute der TO's sind teil der Attribte der BO's....

    Jetzt wäre die Frage, ob es sinn macht, für die Attribute der TO's ein Interface zu definieren,
    dass dann sowohl von BO's als auch von TO's implementiert wird.

    Damit würde ich erreichen, dass bei einer Änderung an den Attributen, der Compiler mir schon
    Meldung liefern würde, wenn ich das z.B. bei den BO's bzw. TO's oder umgekehrt etwas vergesse...

    Dadurch bringe ich wieder eine Kopplung zwischen TO's und BO's ein....

MfG
Karl Heinz Marbaise


----------



## Gast (5. Aug 2008)

Hallo,

Mal ein paar Ideen, die sich bei kleineren Projekten bewaehrt haben. 

Ziel war die Trennung von Entitaeten und "Businesslogik (BL)".

Die Entitaeten wurden "normal" mit Blick auf die Persistenz implementiert.

Im Bereich BL wurden Interfaces erstellt, die wiederum von den Entitaeten impl. wurden.

Vorteile:

- In den Services muessten keine weiteren Objecte erstellt werden.
- Es gab einen Ort fuer die Implementierungen.
- Es konnte unter Beruecksichtigung der Persistenz relativ vernueftig auf der Basis von OO entwickelt werden.

Nachteile:
- Die Methodennamen der Businessinterfaces duerften sich nicht ueberschneiden. Damit zum Teil Verlust einer Gliederungsbene.
- Trennung von BL und Persistenz war durch Interfaces gewaehrleistet.

Anmerkung zu "eurem" Ansatz:

- Denkt daran das eure TO eigene equals und hashCode Methoden benoetigen.
- Was passiert bei der Rueckgabe von Listen oder komplexen Objecten.

Bsp:

UserEntity

- userName:String
- address: AddressEntity

AddressEntity
- street:String

------------------
UserTO
- userName :String
- address:AddressTO

Damit muesstet ihr in den Services/DAO's die komplette Struktur neu aufbauen!

Wie siehts bei Listen aus? Ihr muesstest entweder die komplette Liste durch iterieren, um die Objecte zu erzeugen, Lazy Loading waere dann hinfaellig, oder eine Konvertierungsliste implementieren, die nur bei Bedarf das Object umwandelt....

Gruesse


----------

