2010-10-27 8 views
38

Ich lese in einigen Artikeln DAO ist nicht zwingend mit Hibernate und seine Umsetzung ist durch "es hängt", mit anderen Worten, wir können zwischen ORM vs DAO Muster wählen.DAO vs ORM (Winterschlaf) Muster

Ok, nehmen wir an, dass ich nicht ein DAO-Muster verwenden möchte, also verwende ich nur Sitzung CRUD und Abfrage-Operation von Hibernate (mein ORM) zur Verfügung gestellt.

Speziell für die "Suche" und "finden" Abfragen ist nicht korrekt, um sie immer neu zu schreiben, so ist vernünftig zu denken, sie in eine Klasse zu setzen.

Aber dann ist diese Klasse ein einfaches DAO ohne alle Implementierung von DAO-Muster und DAOFactory, nur eine leichte Implementierung eines DAO. Also, der Punkt ist, dass wir immer ein DAO brauchen und die Wahl ist schwere DAO-Implementierung gegen leichte DAO-Implementierung?

Was ich gesagt habe, ist falsch?

EDIT Ein weiteres Problem, das ich habe, ist, wo Put dao Wechselwirkungen, zum Beispiel muss ich einen Benutzernamen und ein Protokoll der Login (nutzloses Beispiel ich weiß ...)

So in einem DAO schreiben Muster Ich habe alle generischen Dao-Implementierungen, eine DAOFactory und schließlich UserHibernateDAO und LogHibernateDAO. Der Anmeldevorgang ist eine Business-Methode:

private void login(String username, String password){ 
    daoFactory.beginTransaction(); 
    UserDAO userDao=daoFactory.HIBERNATE.getUserDao(); 
    LogDAO logDao=daoFactory.HIBERNATE.getLogDao(); 
    if(userDao.checkAccount(username, password){ 
     User user=userDao.findByAccount(username, password); 
     logDao.save(new Log("log-in", user); 
    } 
    daoFactory.commit(); 
} 

Ist das sinnvoll? Kann ich Dao auf diese Weise benutzen? Wenn ich Handle-Ausnahme behandeln möchte, ist der bessere Ort, um es zu tun, eine Business-Logik?

EDIT2 Nehmen wir an, ein DAO Muster zu verwenden, ist der Hauptgrund, es zu tun in der Lage sein, um zwischen tecnhology (ORM-> JDBC etc ..), es ist alles in Ordnung und ok, aber wo kann ich Handle Hibernate Sitzung und Transaktion? Ich kann es nicht in ein DAO setzen, es ist anty Muster, und ich kann es nicht in eine Service-Schicht setzen, weil in einem hipohtetycal Schalter ich alle diese Transaktion entfernen muss (weil andere Technik sie nicht verwenden kann).

+0

mögliche Duplikate von [Ich fand JPA, oder ähnlich, ermutigen nicht DAO-Muster] (http://stackoverflow.com/questions/2100115/i-found-jpa- oder-alike-dont-encourage-dao- Muster) – Bozho

+0

Vielleicht Check-out mein Blog-Post darüber. Ich schlage vor, wie JPA mit DAO-Muster so einfach und DRY wie möglich zu kombinieren: http://codeblock.engio.net/?p=180 – bennidi

Antwort

68

ORM und DAO sind orthogonale Konzepte. Einer hat damit zu tun, wie Objekte zu Datenbanktabellen zugeordnet werden, der andere ist ein Entwurfsmuster zum Schreiben von Objekten, die auf Daten zugreifen. Du wählst nicht zwischen ihnen. Sie können ORM und DAO die gleiche Anwendung haben, genauso wie Sie kein ORM benötigen, um das DAO-Muster zu verwenden.

Das sagte, während Sie nie wirklich brauchen nichts, sollten Sie DAOs verwenden. Das Muster eignet sich für einen modularisierten Code. Du behälst all deine Beharrungslogik an einem Ort (Trennung von Bedenken, Bekämpfung undichter Abstraktionen). Sie erlauben sich, den Datenzugriff getrennt vom Rest der Anwendung zu testen. Und Sie erlauben sich, den Rest der Anwendung zu testen, die vom Datenzugriff isoliert ist (d. H. Sie können Ihre DAOs verspotten).

Außerdem ist das Folgen des DAO-Musters einfach, selbst wenn die Implementierung des Datenzugriffs schwierig sein kann. So kostet es Sie sehr wenig (oder nichts) und Sie gewinnen viel.

BEARBEITEN - In Bezug auf Ihr Beispiel sollte Ihre Login-Methode in einer Art von AuthenticationService sein. Dort können Sie Ausnahmen behandeln (in der Login-Methode). Wenn Sie Spring verwenden, könnte es eine Menge Dinge für Sie verwalten: (1) Transaktionen, (2) Abhängigkeitsinjektion. Sie müssten nicht Ihre eigenen Transaktionen oder Dao-Factories schreiben, Sie könnten einfach Transaktionsgrenzen für Ihre Servicemethoden definieren und Ihre DAO-Implementierungen als Beans definieren und sie dann in Ihren Service einbinden.

EDIT2

Der Hauptgrund um das Muster zu verwenden ist Anliegen zu trennen. Das bedeutet, dass sich der gesamte Persistenz-Code an einem Ort befindet. Ein Nebeneffekt davon ist die Testfähigkeit und Wartbarkeit und die Tatsache, dass dies später den Umstieg erleichtert. Wenn Sie Hibernate-basierte DAOs erstellen, können Sie die Sitzung im DAO absolut manipulieren, was Sie tun sollten. Das Anti-Muster ist der Fall, wenn Persistenzcode außerhalb der Persistenzschicht auftritt (Gesetz der undichten Abstraktionen).

Transaktionen sind ein bisschen komplizierter. Auf den ersten Blick scheinen Transaktionen ein Problem der Beharrlichkeit zu sein, und sie sind es auch. Aber sie sind nicht nur eine Frage der Beharrlichkeit. Transaktionen sind auch ein Anliegen Ihrer Dienste, da Ihre Dienstmethoden eine "Arbeitseinheit" definieren sollten, was bedeutet, dass alles, was in einer Dienstmethode geschieht, atomar sein sollte. Wenn Sie Transaktionen im Ruhezustand verwenden, müssen Sie den Transaktionscode für den Ruhezustand außerhalb Ihrer DAOs schreiben, um Transaktionsgrenzen für Dienste zu definieren, die viele DAO-Methoden verwenden.

Beachten Sie jedoch, dass die Transaktionen unabhängig von Ihrer Implementierung sein können - Sie benötigen Transaktionen, unabhängig davon, ob Sie Hibernate verwenden oder nicht. Beachten Sie auch, dass Sie die Hibernate-Transaktionsmaschinerie nicht verwenden müssen - Sie können containerbasierte Transaktionen, JTA-Transaktionen usw. verwenden.

Kein Zweifel, wenn Sie Spring oder etwas ähnliches nicht verwenden, werden Transaktionen ausgeführt sei ein Schmerz. Ich empfehle Ihnen, Spring zu verwenden, um Ihre Transaktionen zu verwalten, oder die EJB-Spezifikation, in der Sie glauben, Sie können Transaktionen um Ihre Dienste mit Anmerkungen definieren.

Überprüfen Sie die folgenden Links für Container-basierte Transaktionen.

Container-Managed Transactions

Sessions And Transactions

Was aus dieser Ich sammle ist, dass man leicht die Transaktionen außerhalb der DAOs auf der Service-Ebene definieren, und Sie brauchen keine Transaktionscode zu schreiben.

Eine andere (weniger elegante) Alternative besteht darin, alle atomaren Einheiten der Arbeit in DAOs zu setzen. Sie könnten CRUD-DAOs für die einfachen Operationen und dann kompliziertere DAOs verwenden, die mehr als einen CRUD-Vorgang ausführen. Auf diese Weise bleiben Ihre programmatischen Transaktionen im DAO und Ihre Dienste würden die komplizierteren DAOs aufrufen und müssten sich keine Gedanken über die Transaktionen machen.

Der folgende Link ist ein gutes Beispiel dafür, wie die DAO Muster, das Sie

vereinfachen AO vs ORM(hibernate) pattern

(Thanx @daff)

Beachten Sie, wie die Definition der Schnittstelle es, dass so Code helfen kann, macht Ihre Geschäftslogik kümmert sich nur um das Verhalten von UserDao. Es kümmert sich nicht um die Implementierung. Sie könnten ein DAO mit Hibernate oder nur JDBC schreiben. Sie können also Ihre Datenzugriffsimplementierung ändern, ohne den Rest Ihres Programms zu beeinträchtigen.

+0

ok, aber wenn ich nicht DAO-Muster verwenden, wie ich fortfahren muss ? Mit anderen Worten, mit Hibernate und OHNE DAO, wo ich meine Entity CRUD Logik und HQL Queues oder Kriterien Abfragen etc ...? – blow

+1

@blow, das ist der ganze Punkt. Sie müssen den Persistenz-Code irgendwo platzieren. Und Sie sollten es von der Geschäftslogik Ihrer App getrennt halten. Warum also nicht in ein DAO? Mit anderen Worten, Sie werden ein DAO schreiben, die Frage ist, werden Sie dem Muster folgen. – hvgotcodes

+0

Vielen Dank für die Erklärung, im Moment möchte ich nicht den Frühling verwenden, um DAO zu verwalten, zuerst möchte ich wissen, wie DAO Muster arbeiten und wenn ich es wirklich brauche. PS. Ich habe noch einen kleinen Zweifel, ich habe die erste Frage bearbeitet. – blow

11

Nein, ich denke nicht, dass das korrekt ist. ORM ist eine Möglichkeit, DAO zu implementieren; Sie können DAO ohne ORM auswählen.

Sie haben es rückwärts: Ich würde ORM als schwerer als DAO betrachten, weil die Abhängigkeiten größer sind. Ich kann ein DAO in JDBC ohne ORM schreiben. Das ist leichter, IMO.

Ob wir zustimmen oder nicht, hängt davon ab, wie wir "leicht" und "schwer" definieren. Ich gehe nach Abhängigkeiten - die Anzahl der zusätzlichen JARs benötigt über dem JDK selbst.

25

Lassen Sie mir ein Quellcode Beispiel eine gute Antwort auf hvgotcodes:

public class Application 
{ 
    private UserDao userDao; 

    public Application(UserDao dao) 
    { 
     // Get the actual implementation 
     // e.g. through dependency injection 
     this.userDao = dao; 
    } 

    public void login() 
    { 
     // No matter from where 
     User = userDao.findByUsername("Dummy"); 
    } 
} 


public interface UserDao 
{ 
    User findByUsername(String name); 
} 

public class HibernateUserDao implements UserDao 
{ 
    public User findByUsername(String name) 
    { 
     // Do some Hibernate specific stuff 
     this.session.createQuery... 
    } 
} 

public class SqlUserDao implements UserDao 
{ 
    public User findByUsername(String name) 
    { 
     String query = "SELECT * FROM users WHERE name = '" + name + "'"; 
     // Execute SQL query and do mapping to the object 
    } 
} 

public class LdapUserDao implements UserDao 
{ 
    public User findByUsername(String name) 
    { 
     // Get this from LDAP directory 
    } 
} 

public class NoSqlUserDao implements UserDao 
{ 
    public User findByUsername(String name) 
    { 
     // Do something with e.g. couchdb 
     ViewResults resultAdHoc = db.adhoc("function (doc) { if (doc.name=='" + name + "') { return doc; }}"); 
     // Map the result document to user 
    } 
} 

So, wie bereits erwähnt, ist DAO ein Entwurfsmuster Kopplung zwischen Ihrer Anwendung zu minimieren und Sie Backend während ORM behandelt, wie man Objekte in eine objektrelationale Datenbank mappen (was die Kopplung zwischen der Datenbank und Ihrer Anwendung reduziert, aber am Ende ohne Verwendung eines DAO ist Ihre Anwendung abhängig vom verwendeten ORM oder auf einer höheren Ebene ein Standard wie JPA).

Daher wäre es ohne DAOs wirklich schwierig, Ihre Anwendung zu ändern (z. B. Verschieben in eine NoSQL-Datenbank anstelle eines JPA-kompatiblen ORM).

+0

danke Daff Ihr Beispiel ist sehr klar. Sie sagen: "Ohne ein DAO zu verwenden, wäre Ihre Anwendung abhängig vom verwendeten ORM oder auf höherer Ebene von einem Standard wie JPA", ok, aber ich muss trotzdem ein einfaches DAO schreiben, ich kann mit einem anderen Namen wie UserService oder UserManager oder UserSessionFacade, aber es ist ein einfaches DAO ... Also, die wirkliche Wahl ist zwischen einer echten Implementierung eines DAO mit einigen Vorteilen oder einem einfachen Hibernate DAO, der alle meine CRUD-Operationen oder Abfragen für eine bestimmte Entität inkapsuled. – blow

+0

gutes und einfaches Beispiel ... – hvgotcodes

+0

THanks. @blow: Wenn Sie einen service-basierten Ansatz verwenden, könnten Sie Ihre Dienste als DAO sehen und wenn Sie keine weitere Abstraktionsebene benötigen, brauchen Sie die DAOs nicht dazwischen. In größeren Anwendungen lasse ich die Dienste normalerweise das Session- und Transaktionsmanagement handhaben und leite die eigentliche Arbeit zu den DAOs um. Aber das hängt davon ab. – Daff