2010-10-27 30 views
38

ho letto in alcuni articoli DAO non è obbligatorio con Hibernate e la sua attuazione è di "dipende", in altre parole, possiamo scegliere tra ORM vs modello DAO.DAO vs ORM (Hibernate) modello

Ok, supponiamo di non voler utilizzare un modello DAO, quindi im utilizzando solo la sessione CRUD e l'operazione di query fornita da hibernate (my ORM).

Soprattutto per le query "cerca" e "trova" non è corretto riscriverli sempre, quindi è ragionevole pensare di inserirli in una classe.

Ma questa classe è un DAO semplice senza tutte le implementazioni del modello DAO e DAOFactory, solo un'implementazione leggera di un DAO. Quindi, il punto è che abbiamo bisogno sempre di un DAO e la scelta è l'implementazione DAO pesante rispetto all'implementazione DAO leggera?

Quello che ho detto è sbagliato?

EDIT Un altro problema che ho è in cui le interazioni put Dao, per esempio ho il login di un utente e di scrivere un registro del login (inutile esempio lo so ...)

Così in un DAO modello ho tutte le implementazioni dao generiche, una DAOFactory e, infine, UserHibernateDAO e LogHibernateDAO. L'operazione di login è un metodo affari:

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(); 
} 

È questo ragionevole? Posso usare dao in questo modo? Se voglio gestire l'eccezione, il posto migliore per farlo è una logica di business?

EDIT2 Supponiamo di utilizzare un modello DAO, la ragione principale per farlo è quello di essere in grado di passare da Tecnhology (ORM-> JDBC, ecc ..), è tutto bene e OK, ma dove posso gestire la sessione di ibernazione e la transazione? Non riesco a metterlo in una DAO, è modello Anty, e non riesco a metterlo in un livello di servizio, siccome in uno switch hipohtetycal devo togliere tutta questa operazione (siccome altro Tecnhology non li possono utilizzare).

+0

possibile duplicato di [Ho trovato JPA, o simili, non incoraggiare pattern DAO] (http://stackoverflow.com/questions/2100115/i-found-jpa-or-alike-dont-encourage-dao- modello) – Bozho

+0

Forse verifica il mio post sul blog su quello. Propongo come combinare JPA con pattern DAO come diretto e DRY il più possibile: http://codeblock.engio.net/?p=180 – bennidi

risposta

68

ORM e DAO sono concetti ortogonali. Uno ha a che fare con il modo in cui gli oggetti sono mappati alle tabelle del database, l'altro è un modello di progettazione per scrivere oggetti che accedono ai dati. Non scegli "tra" loro. È possibile avere ORM e DAO è la stessa applicazione, proprio come non è necessario ORM per utilizzare il modello DAO.

Detto questo, mentre non si è mai realmente nello stato , è necessario utilizzare DAO. Il modello si presta a codice modulare. Mantieni tutte le tue logiche di persistenza in un unico posto (separazione delle preoccupazioni, lotta contro le astrazioni che perdono). Ti permetti di testare l'accesso ai dati separatamente dal resto dell'applicazione. E ti permetti di testare il resto dell'applicazione isolata dall'accesso ai dati (ad esempio puoi prendere in giro i tuoi DAO).

Inoltre, seguire il modello DAO è facile, anche se l'implementazione dell'accesso ai dati può essere difficile. Quindi ti costa pochissimo (o niente) e guadagni molto.

EDIT - Rispetto all'esempio, il metodo di accesso deve essere in una sorta di AuthenticationService. È possibile gestire le eccezioni lì (nel metodo di accesso). Se hai usato Spring, potrebbe gestire un sacco di cose per te: (1) transazioni, (2) iniezione di dipendenza. Non è necessario scrivere le proprie transazioni o fabbriche dao, è sufficiente definire i limiti delle transazioni attorno ai metodi di servizio e definire le implementazioni DAO come bean e quindi collegarle al servizio.

EDIT2

Il motivo principale per utilizzare il modello è di separare le preoccupazioni. Ciò significa che tutto il tuo codice di persistenza è in un posto. Un effetto collaterale di questo è, test-abilità e manutenibilità, e il fatto che questo rende più facile cambiare le implementazioni in seguito. Se stai creando DAO basati su Hibernate, puoi assolutamente manipolare la sessione nel DAO, questo è ciò che dovresti fare. Il pattern anti è quando il codice relativo alla persistenza si verifica al di fuori dello strato di persistenza (legge delle astrazioni che perdono).

Le transazioni sono un po 'più complicate. A prima vista, le transazioni potrebbero sembrare una preoccupazione di persistenza, e lo sono. Ma non sono solo una preoccupazione di persistenza. Le transazioni sono anche una preoccupazione dei tuoi servizi, in quanto i tuoi metodi di servizio dovrebbero definire una "unità di lavoro", il che significa che tutto ciò che accade in un metodo di servizio dovrebbe essere atomico. Se si utilizzano le transazioni di ibernazione, sarà necessario scrivere il codice di transazione in ibernazione al di fuori dei DAO, per definire i limiti delle transazioni intorno ai servizi che utilizzano molti metodi DAO.

Tuttavia, si noti che le transazioni possono essere indipendenti dall'implementazione: sono necessarie delle transazioni indipendentemente dal fatto che si utilizzi o meno l'ibernazione. Si noti inoltre che non è necessario utilizzare il meccanismo di transazione in ibernazione - è possibile utilizzare transazioni basate su container, transazioni JTA, ecc.

Non c'è dubbio che se non si utilizza Spring o qualcosa di simile, le transazioni stanno per essere un dolore Consiglio vivamente di utilizzare Spring per gestire le transazioni o la specifica EJB in cui I crede che sia possibile definire le transazioni intorno ai servizi con annotazioni.

Controlla i seguenti collegamenti per le transazioni basate su container.

Container-Managed Transactions

Sessions And Transactions

Quello che sto raccogliendo da questo è che si può facilmente definire le transazioni al di fuori dei DAO al livello di servizio, e non è necessario scrivere alcun codice di transazione.

Un'altra alternativa (meno elegante) consiste nel mettere tutte le unità atomiche di lavoro all'interno di DAO. È possibile avere DAO CRUD per le operazioni semplici e quindi DAO più complicati che eseguono più operazioni CRUD. In questo modo, le tue transazioni programmatiche rimangono nel DAO ei tuoi servizi chiamerebbero i DAO più complicati e non dovrebbero preoccuparsi delle transazioni.

Il seguente link è un buon esempio di come il modello DAO consente di semplificare il codice

AO vs ORM(hibernate) pattern

(thanx @daff)

Notate come la definizione dell'interfaccia fa sì che la tua logica di business si preoccupa solo del comportamento di UserDao. Non si preoccupa dell'attuazione. È possibile scrivere un DAO utilizzando la sospensione o semplicemente JDBC. In questo modo è possibile modificare l'implementazione dell'accesso ai dati senza influire sul resto del programma.

+0

ok ma se scelgo di non usare il pattern DAO, come devo procedere ? in altre parole, con Hibernate e WITHOUT DAO, dove metto la mia logica di entità CRUD e le code o le query dei criteri HQL ecc ...? – blow

+1

@blow, questo è l'intero punto. Devi mettere il codice di persistenza da qualche parte. E dovresti tenerlo separato dalla logica di business della tua app. Quindi, perché non metterlo in un DAO? In altre parole, scriverai un DAO, la domanda è, seguirai il modello. – hvgotcodes

+0

grazie per la spiegazione, al momento non voglio usare spring per gestire DAO, prima voglio sapere come funziona il pattern DAO e se ne ho davvero bisogno. PS. ho un altro piccolo dubbio, ho modificato la prima domanda. – blow

11

No, non credo che sia corretto. ORM è un modo per implementare DAO; puoi scegliere di fare DAO senza ORM.

ce l'hai al contrario: penso che potrei ORM per essere più pesante di DAO, perché le dipendenze sono maggiori. Posso scrivere un DAO in JDBC diritto senza ORM. È più leggero, IMO.

O se non siamo d'accordo dipende da come noi definiamo "luce" e "pesante". Vado per dipendenze: il numero di JAR aggiuntivi richiesti oltre il JDK stesso.

25

Permettetemi di fornire un esempio di codice sorgente per hvgotcodes buona risposta:

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 
    } 
} 

Così, come già accennato, DAO è un modello di progettazione per ridurre al minimo l'accoppiamento tra l'applicazione e si backend mentre offerte ORM con il modo di mappare gli oggetti in un database relazionale oggetto (che riduce l'accoppiamento tra il database e l'applicazione, ma alla fine, senza utilizzare un DAO l'applicazione sarebbe dipesa dall'ORM utilizzato o su un livello superiore uno standard come JPA).

Pertanto, senza DAO, sarebbe davvero difficile cambiare l'applicazione (ad esempio, passare a un database NoSQL anziché a un ORM compatibile con JPA).

+0

grazie a Daff il tuo esempio è molto chiaro. dici "senza usare un DAO la tua applicazione sarebbe dipesa dall'ORM usato o ad un livello più alto di uno standard come JPA", ok, ma ho comunque bisogno di scrivere un DAO semplice, posso chiamare con altri nomi come UserService o UserManager o UserSessionfacade, ma è un DAO semplice ... Quindi, la vera scelta è tra un'implementazione reale di un DAO con alcuni vantaggi, o un semplice DAO di ibernazione che incapsula tutte le mie operazioni CRUD o query per una certa entità. – blow

+0

esempio semplice e buono ... – hvgotcodes

+0

Grazie. @blow: Se stai utilizzando un approccio basato su servizi, potresti vedere i tuoi servizi come DAO e, se non hai bisogno di un altro livello di astrazione, non ti occorrono i DAO in mezzo. Nelle applicazioni più grandi di solito permetto ai servizi di gestire la sessione e la gestione delle transazioni e di reindirizzare il lavoro effettivo ai DAO. Ma ciò dipende – Daff