Spring DAO vs Spring ORM vs Spring JDBC


103

Stavo esaminando le tecnologie di accesso ai dati supportate da Spring e ho notato che menziona più opzioni e non sono sicuro della differenza tra loro:

Da quanto ho capito, Spring JDBC fornisce modelli per ridurre il codice boilerplate per accedere a un database attraverso un semplice vecchio modo: scrivi le tue query SQL.

Spring-ORM fornisce modelli semplificati per l'accesso ai database tramite tecnologie ORM, come Hibernate, My (i) Batis ecc.

Spring-DAO come da sito web di Spring:

Il supporto DAO (Data Access Object) in primavera ha lo scopo di semplificare il lavoro con tecnologie di accesso ai dati come JDBC, Hibernate o JDO in modo coerente

Sono un po 'chiaro su ORM e JDBC in quanto mirano a diversi modi di accedere al DB. Ma Spring-DAO è semplicemente confuso!

Qualcuno potrebbe chiarire quali sono esattamente le differenze tra questi tre? Quale dovrebbe essere preferito in quali scenari?

Inoltre, è Spring-DATAdisponibile anche un altro progetto ( http://projects.spring.io/spring-data/ ) Ora, è una specie di progetto padre per tutti i tecnici di accesso ai dati supportati da Spring o è solo un nuovo nome per Spring -DAO?

Risposte:


162

Ecco un'introduzione a ciascuna tecnologia menzionata.

Spring-DAO

Spring-DAO non è un modulo spring in senso stretto, ma piuttosto convenzioni che dovrebbero imporre di scrivere DAO e di scriverli bene. In quanto tale, non fornisce interfacce, implementazioni o modelli per accedere ai dati. Quando si scrive un DAO, è necessario annotarli con in @Repositorymodo che le eccezioni collegate alla tecnologia sottostante (JDBC, Hibernate, JPA, ecc.) Siano tradotte in modo coerente nella DataAccessExceptionsottoclasse appropriata .

Ad esempio, supponiamo che ora stai utilizzando Hibernate e il tuo livello di servizio cattura HibernateExceptionper reagire ad esso. Se si passa a JPA, le interfacce DAO non dovrebbero cambiare e il livello di servizio verrà comunque compilato con blocchi che catturano HibernateException, ma non si inseriranno mai questi blocchi poiché i DAO ora lanciano JPA PersistenceException. Usando @Repositorysul tuo DAO, le eccezioni legate alla tecnologia sottostante vengono tradotte in Spring DataAccessException; il tuo livello di servizio rileva queste eccezioni e se decidi di cambiare la tecnologia di persistenza, la stessa primavera DataAccessExceptionsverrà comunque lanciata poiché la primavera ha tradotto le eccezioni native.

Si noti tuttavia che questo ha un utilizzo limitato per i seguenti motivi:

  1. Di solito non dovresti intercettare le eccezioni di persistenza, poiché il provider potrebbe aver annullato la transazione (a seconda del sottotipo di eccezione esatto) e quindi non dovresti continuare l'esecuzione con un percorso alternativo.
  2. La gerarchia delle eccezioni è solitamente più ricca nel tuo provider rispetto a quella fornita da Spring e non esiste una mappatura definitiva da un provider all'altro. Affidarsi a questo è pericoloso. Questa è comunque una buona idea con cui annotare i DAO @Repository, poiché i bean verranno aggiunti automaticamente dalla procedura di scansione. Inoltre, Spring può aggiungere altre utili funzionalità all'annotazione.

Spring-JDBC

Spring-JDBC fornisce la classe JdbcTemplate, che rimuove il codice idraulico e ti aiuta a concentrarti sulla query e sui parametri SQL. Devi solo configurarlo con a DataSource, quindi puoi scrivere codice come questo:

int nbRows = jdbcTemplate.queryForObject("select count(1) from person", Integer.class);

Person p = jdbcTemplate.queryForObject("select first, last from person where id=?", 
             rs -> new Person(rs.getString(1), rs.getString(2)), 
             134561351656L);

Spring-JDBC fornisce anche un JdbcDaoSupport, che puoi estendere per sviluppare il tuo DAO. Fondamentalmente definisce 2 proprietà: un DataSource e un JdbcTemplate che possono essere utilizzati entrambi per implementare i metodi DAO. Fornisce inoltre un traduttore delle eccezioni dalle eccezioni SQL alle Spring DataAccessExceptions.

Se prevedi di usare jdbc semplice, questo è il modulo che dovrai usare.

Primavera-ORM

Spring-ORM è un modulo ombrello che copre molte tecnologie di persistenza, ovvero JPA, JDO, Hibernate e iBatis. Per ciascuna di queste tecnologie, Spring fornisce classi di integrazione in modo che ciascuna tecnologia possa essere utilizzata seguendo i principi di configurazione di Spring e si integra senza problemi con la gestione delle transazioni di Spring.

Per ogni tecnologia, la configurazione consiste fondamentalmente nell'iniettare un DataSourcebean in una sorta di bean SessionFactoryo EntityManagerFactoryaltro. Per JDBC puro, non sono necessarie tali classi di integrazione (a parte JdbcTemplate), poiché JDBC si basa solo su un DataSource.

Se prevedi di utilizzare un ORM come JPA o Hibernate, non avrai bisogno di spring-jdbc, ma solo di questo modulo.

Spring-Data

Spring-Data è un progetto ombrello che fornisce un'API comune per definire come accedere ai dati (DAO + annotazioni) in un modo più generico, coprendo sia le origini dati SQL che NOSQL.

L'idea iniziale è quella di fornire una tecnologia in modo che lo sviluppatore scriva l'interfaccia per un DAO (metodi finder) e le classi di entità in modo indipendente dalla tecnologia e, in base alla sola configurazione (annotazioni su DAO e entità + configurazione a molla, sia essa xml o java-based), decide la tecnologia di implementazione, sia essa JPA (SQL) o redis, hadoop, ecc. (NOSQL).

Se si seguono le convenzioni di denominazione definite da spring per i nomi dei metodi finder, non è nemmeno necessario fornire le stringhe di query corrispondenti ai metodi finder per i casi più semplici. Per altre situazioni, devi fornire la stringa di query all'interno delle annotazioni sui metodi finder.

Quando il contesto dell'applicazione viene caricato, spring fornisce proxy per le interfacce DAO, che contengono tutto il codice boilerplate relativo alla tecnologia di accesso ai dati e richiama le query configurate.

Spring-Data si concentra su tecnologie non SQL, ma fornisce comunque un modulo per JPA (l'unica tecnologia SQL).

Qual è il prossimo

Sapendo tutto questo, ora devi decidere cosa scegliere. La buona notizia qui è che non è necessario fare una scelta finale definitiva per la tecnologia. È qui che risiede il potere di Spring: come sviluppatore, ti concentri sul business quando scrivi codice e, se lo fai bene, cambiare la tecnologia sottostante è un dettaglio di implementazione o configurazione.

  1. Definire un modello di dati con classi POJO per le entità e metodi get / set per rappresentare gli attributi dell'entità e le relazioni con altre entità. Avrai sicuramente bisogno di annotare le classi ei campi di entità in base alla tecnologia, ma per ora i POJO sono sufficienti per iniziare. Per ora concentrati solo sui requisiti aziendali.
  2. Definisci le interfacce per i tuoi DAO. 1 DAO copre esattamente 1 entità, ma certamente non avrai bisogno di un DAO per ciascuna di esse, poiché dovresti essere in grado di caricare entità aggiuntive navigando nelle relazioni. Definire i metodi di ricerca seguendo rigide convenzioni di denominazione.
  3. Sulla base di ciò, qualcun altro può iniziare a lavorare sul livello dei servizi, con mock per i tuoi DAO.
  4. Impari le diverse tecnologie di persistenza (sql, no-sql) per trovare la soluzione migliore per le tue esigenze e scegli una di esse. Sulla base di ciò, annoti le entità e implementa i DAO (o lascia che spring li implementi per te se scegli di utilizzare spring-data).
  5. Se i requisiti aziendali si evolvono e la tua tecnologia di accesso ai dati non è sufficiente a supportarla (ad esempio, hai iniziato con JDBC e alcune entità, ma ora hai bisogno di un modello di dati più ricco e JPA è una scelta migliore), dovrai cambiare l'implementazione dei tuoi DAO, aggiungi alcune annotazioni sulle tue entità e modifica la configurazione della molla (aggiungi una definizione EntityManagerFactory). Il resto del codice aziendale non dovrebbe subire altri impatti dalla modifica.

Nota: gestione delle transazioni

Spring fornisce un'API per la gestione delle transazioni. Se prevedi di utilizzare spring per l'accesso ai dati, dovresti utilizzare anche spring per la gestione delle transazioni, poiché si integrano molto bene. Per ciascuna tecnologia di accesso ai dati supportata dalla primavera, esiste un gestore delle transazioni corrispondente per le transazioni locali, oppure puoi scegliere JTA se hai bisogno di transazioni distribuite. Tutti implementano la stessa API, in modo che (ancora una volta) la scelta tecnologica sia solo una questione di configurazione che può essere modificata senza ulteriori impatti sul codice aziendale.

Nota: documentazione di primavera

I collegamenti alla documentazione di Spring che hai citato sono piuttosto vecchi. Ecco la documentazione dell'ultima versione (4.1.6, che copre tutti gli argomenti):

Spring-data non fa parte del framework Spring. C'è un modulo comune che dovresti prima leggere per abituarti ai principi. La documentazione può essere trovata qui:


Apprezzo questa risposta usando il termine "ombrello" in alcune descrizioni qui (come Spring Data), identificando che ci sono sotto-componenti / moduli all'interno (piuttosto che un ombrello che è più specifico del dominio). E menzionare Spring Data è molto utile nel contesto qui, anche se non è stato menzionato nella domanda.
cellepo

Non spring-jdbcfornisce altri strumenti utili non menzionati qui? Ad esempio, trovo SimpleJdbcInsertmolto pulito e utile sia per l'inserimento di una singola voce che per il bulk (fino a una scala ragionevole, ovviamente).
Nom1fan

3

Spring DAO ( D ata A ccess O bject): è un oggetto che fornisce un'interfaccia astratta ai framework di implementazione JDBC, ovvero Spring DAO è un concetto generalizzato per accedere a JDBC e Hibernate, MyBatis, JPA, JDO utilizzando le sue singole classi di supporto. E fornisce una gerarchia di eccezioni generalizzata definendo l' @Repositoryannotazione. Questa annotazione definisce il contenitore Spring per la traduzione dell'eccezione SQL dalla gerarchia indipendente dalla SQLExceptionstrategia di accesso ai dati di Spring DataAccessException.

ad esempio, le eccezioni specifiche della piattaforma sono catture e quindi rilanciate come una delle eccezioni di accesso ai dati non controllate di Spring.


Spring JDBC : per JDBC semplice utilizziamo questo modulo, che dipende solo da DataSourceclassi Template come JdbcTemplate, NamedParameterJdbcTemplate(wraps JdbcTemplate) e SimpleJdbcTemplateper ridurre i problemi di taglio incrociato.

public class EmployeeDao {  
private JdbcTemplate jdbcTemplate;  

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {  
    this.jdbcTemplate = jdbcTemplate;  
}  

public int saveEmployee(Employee e){  
    return jdbcTemplate.update(query);  
}  
public int updateEmployee(Employee e){  
    return jdbcTemplate.update(query);  
}  
public int deleteEmployee(Employee e){  
       return jdbcTemplate.update(query);  
}  

}  

e in Spring XML:

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>

Spring JDBC fornisce anche JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport, che sono di supporto (es conveniente ) modo per estendere e sviluppare la nostra DAO un'interfaccia astratta come segue:

public interface EmployeeDao {

    public void saveEmployee(Employee emp);
}

public class EmployeeDaoImpl extends JdbcDaoSupport implements EmployeeDao{

    @Override
    public void saveEmployee(Employee emp) {

        Object[] inputs = new Object[] {emp.getName(), emp.getSalary(), emp.getDept()};
        getJdbcTemplate().update(query, inputs);
    }
}

e in primavera XML:

<bean id="employeeDAO" class="EmployeeDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>

Spring ORM: per il supporto di strumenti ORM come Hibernate, JPA, MyBatis ... integra facilmente Spring iniettando DataSourceinsieme alle seguenti classi e rispettive DaoSupportclassi.

  • SessionFactory per Hibernate
  • EntityManagerFactory per JPA,
  • SqlSessionFactory per MyBatis

1

La libreria spring-dao è stata interrotta nella versione 2.0.8 (gennaio 2008). Le classi in spring-dao sono state copiate in spring-tx. Quindi, se hai bisogno di una classe che trovi in ​​spring-dao, aggiungi invece la dipendenza a spring-tx . ( Fonte .)


0

È possibile creare l'interfaccia come SomeObjectDaoe quindi creare diverse implementazioni di questa interfaccia, come JdbcSomeObjectDao, HibernateSomeObjectDao. Quindi nella tua SomeObjectServiceclasse opererai SomeObjectDaosull'interfaccia e inietterai lì una delle implementazioni concrete. Quindi ogni implementazione di SomeObjectDaonasconderà i dettagli, indipendentemente dal fatto che utilizzi JDBC, ORM ecc.

Di solito JDBC e diverse implementazioni di ORM generano diversi tipi di eccezioni. Il supporto DAO di Spring può mappare queste diverse eccezioni specifiche della tecnologia alle comuni eccezioni Spring DAO. Quindi sei più separato dall'attuale implementazione. Anche il supporto DAO di Spring offre un set di *DataSupportclassi astratte che aiutano ancora di più nello sviluppo DAO. Quindi, oltre a implementare la tua SomeObjectDaointerfaccia, puoi estendere una delle *DataSupportclassi di Spring .


quindi intendi, spring-dao astrae le eccezioni specifiche di Hibernate / JDO / JDBC e fornisce un insieme standard di eccezioni? Ne ha templatesper accedere al db? o è solo un'astrazione da utilizzare con altri componenti a molla? Ad esempio, è possibile scrivere codice che utilizza solo spring-dao per accedere a db (senza utilizzare spring-jdbc, spring-orm, hibernate o qualsiasi altro framework)?
Pat

0

Come ulteriore informazione. Ti suggerisco di utilizzare Spring Data JPA. Utilizzando annotazioni come: @Repository, @Service. Ti mostro un esempio:

@Repository("customerEntitlementsRepository")
public interface CustomerEntitlementsRepository extends CrudRepository<BbsExerul, BbsExerulPK> {

  @Query(value = "SELECT " + "CONTRACT_NUMBER, EXECUTIVE_NUMBER, " + "GROUP_VALUE, " + "CODE, "
      + "SUBCODE, " + "CURRENCY " + "FROM BBS_EXERUL " + "WHERE CONTRACT_NUMBER =:clientId AND "
      + "EXECUTIVE_NUMBER =:representativeId", nativeQuery = true)
  Collection<CustomerEntitlementsProjection> getFieldsExerul(@Param("clientId") String clientId,
      @Param("representativeId") String representativeId);

}

Dove CustomerEntitlementsProjection è la proiezione di primavera, collegata alla tua entità o pojo DTO;

@Projection(name = "customerEntitlementsProjection", types = { BbsExerul.class })
public interface CustomerEntitlementsProjection {

  String getContractNumber();

  String getExecutiveNumber();

1
Formatta il codice in blocchi di codice in modo che sia leggibile.
CertainPerformance
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.