Spring DAO vs Spring ORM vs Spring JDBC

103

Przeglądałem technologie dostępu do danych obsługiwane przez Spring i zauważyłem, że wspomina o wielu opcjach i nie jestem pewien, jaka jest między nimi różnica:

Jak rozumiem, Spring JDBC zapewnia szablony do redukcji standardowego kodu dostępu do bazy danych w zwykły stary sposób - piszesz własne zapytania SQL.

Spring-ORM zapewnia uproszczone szablony dostępu do baz danych za pośrednictwem technologii ORM, takich jak Hibernate, My (i) Batis itp.

Spring-DAO na stronie internetowej Springa:

Obsługa Data Access Object (DAO) w Spring ma na celu ułatwienie pracy z technologiami dostępu do danych, takimi jak JDBC, Hibernate czy JDO w spójny sposób

Mam trochę jasności co do ORM vs JDBC, ponieważ mają one na celu różne sposoby dostępu do bazy danych. Ale Spring-DAO jest po prostu mylące!

Czy ktoś mógłby wyjaśnić, jakie dokładnie są różnice między tymi trzema? Który powinien być preferowany w poszczególnych scenariuszach?

Spring-DATADostępny jest również inny projekt ( http://projects.spring.io/spring-data/ ) Czy jest to rodzaj projektu nadrzędnego dla wszystkich technologii dostępu do danych obsługiwanych przez Spring, czy jest to po prostu nowa nazwa Spring -DAO?

Poklepać
źródło

Odpowiedzi:

162

Oto wprowadzenie do każdej wymienionej technologii.

Wiosna-DAO

Spring-DAO nie jest modułem sprężynowym w ścisłym tego słowa znaczeniu, ale raczej konwencjami, które powinny dyktować ci pisanie DAO i pisanie ich dobrze. W związku z tym nie zapewnia interfejsów, implementacji ani szablonów dostępu do danych. Podczas pisania DAO należy opatrzyć je adnotacjami @Repository, aby wyjątki związane z podstawową technologią (JDBC, Hibernate, JPA itp.) Były konsekwentnie tłumaczone na odpowiednią DataAccessExceptionpodklasę.

Na przykład załóżmy, że używasz teraz Hibernacji, a Twoja warstwa usług przechwytuje HibernateException, aby na nią zareagować. Jeśli zmienisz na JPA, twoje interfejsy DAO nie powinny się zmienić, a warstwa usług będzie nadal kompilować się z blokami, które przechwytują HibernateException, ale nigdy nie wejdziesz do tych bloków, ponieważ DAO rzucają teraz JPA PersistenceException. Korzystając @Repositoryz DAO, wyjątki powiązane z podstawową technologią są tłumaczone na Spring DataAccessException; Twoja warstwa usług wyłapuje te wyjątki i jeśli zdecydujesz się zmienić technologię trwałości, ten sam Spring DataAccessExceptionsbędzie nadal generowany, ponieważ Spring przetłumaczył natywne wyjątki.

Należy jednak pamiętać, że ma to ograniczone zastosowanie z następujących powodów:

  1. Zwykle nie należy przechwytywać wyjątków trwałości, ponieważ dostawca mógł wycofać transakcję (w zależności od dokładnego podtypu wyjątku), a zatem nie należy kontynuować wykonywania z alternatywną ścieżką.
  2. Hierarchia wyjątków jest zwykle bogatsza w Twoim dostawcy niż to, co zapewnia Spring, i nie ma ostatecznego mapowania od jednego dostawcy do drugiego. Poleganie na tym jest niebezpieczne. Jest to jednak dobry pomysł, aby oznaczyć swoje DAO adnotacjami @Repository, ponieważ ziarna zostaną automatycznie dodane podczas procedury skanowania. Ponadto Spring może dodać inne przydatne funkcje do adnotacji.

Wiosna-JDBC

Spring-JDBC udostępnia klasę JdbcTemplate, która usuwa kod hydrauliczny i pomaga skoncentrować się na zapytaniu SQL i parametrach. Wystarczy skonfigurować go za pomocą a DataSource, a następnie możesz napisać taki kod:

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 zapewnia również wsparcie Jdbc_actionSupport, które możesz rozszerzyć, aby rozwinąć DAO. Zasadniczo definiuje 2 właściwości: DataSource i JdbcTemplate, które mogą być używane do implementacji metod DAO. Zapewnia również translator wyjątków z wyjątków SQL do sprężynowych wyjątków DataAccessExceptions.

Jeśli planujesz używać zwykłego jdbc, jest to moduł, którego będziesz potrzebować.

Spring-ORM

Spring-ORM to moduł parasolowy obejmujący wiele technologii trwałości, a mianowicie JPA, JDO, Hibernate i iBatis. Dla każdej z tych technologii Spring udostępnia klasy integracji, dzięki czemu każda technologia może być używana zgodnie z zasadami konfiguracji Springa i płynnie integruje się z zarządzaniem transakcjami Spring.

Dla każdej techniki, konfiguracja w zasadzie polega na wstrzykiwaniu DataSourcefasoli w jakimś SessionFactorylub EntityManagerFactoryitd fasoli. W przypadku czystego JDBC nie ma potrzeby tworzenia takich klas integracji (poza JdbcTemplate), ponieważ JDBC opiera się tylko na DataSource.

Jeśli planujesz użyć ORM, takiego jak JPA lub Hibernate, nie będziesz potrzebować spring-jdbc, ale tylko ten moduł.

Spring-Data

Spring-Data to projekt parasolowy, który zapewnia wspólny interfejs API do definiowania sposobu uzyskiwania dostępu do danych (DAO + adnotacje) w bardziej ogólny sposób, obejmujący zarówno źródła danych SQL, jak i NOSQL.

Początkowym pomysłem jest zapewnienie technologii, dzięki której programista napisze interfejs dla DAO (metody wyszukiwania) i klasy encji w sposób niezależny od technologii i tylko w oparciu o konfigurację (adnotacje dotyczące DAO i encji + konfiguracja sprężynowa, czy to xml lub java), decyduje o technologii implementacji, czy to JPA (SQL), czy redis, hadoop itp. (NOSQL).

Jeśli zastosujesz się do konwencji nazewnictwa zdefiniowanych przez wiosnę dla nazw metod wyszukiwania, nie musisz nawet podawać ciągów zapytań odpowiadających metodom wyszukiwania w najprostszych przypadkach. W innych sytuacjach musisz podać ciąg zapytania w adnotacjach w metodach wyszukiwania.

Po załadowaniu kontekstu aplikacji spring udostępnia serwery proxy dla interfejsów DAO, które zawierają cały standardowy kod związany z technologią dostępu do danych, i wywołuje skonfigurowane zapytania.

Spring-Data koncentruje się na technologiach innych niż SQL, ale nadal dostarcza moduł dla JPA (jedyna technologia SQL).

Co dalej

Wiedząc to wszystko, musisz teraz zdecydować, co wybrać. Dobra wiadomość jest taka, że ​​nie musisz podejmować ostatecznego ostatecznego wyboru technologii. W tym właśnie tkwi siła Springa: jako programista, pisząc kod, koncentrujesz się na biznesie, a jeśli robisz to dobrze, zmiana podstawowej technologii to implementacja lub szczegół konfiguracji.

  1. Zdefiniuj model danych z klasami POJO dla jednostek i pobierz / ustaw metody reprezentujące atrybuty jednostki i relacje z innymi jednostkami. Z pewnością będziesz musiał dodać adnotacje do klas encji i pól w oparciu o technologię, ale na razie wystarczy POJO, aby zacząć. Skoncentruj się na razie na wymaganiach biznesowych.
  2. Zdefiniuj interfejsy dla swoich DAO. 1 DAO obejmuje dokładnie 1 obiekt, ale z pewnością nie będziesz potrzebować DAO dla każdego z nich, ponieważ powinieneś być w stanie załadować dodatkowe encje, nawigując po relacjach. Zdefiniuj metody wyszukiwania zgodnie ze ścisłymi konwencjami nazewnictwa.
  3. Na tej podstawie ktoś inny może rozpocząć pracę nad warstwą usług z makietami dla Twoich DAO.
  4. Uczysz się różnych technologii trwałości (sql, no-sql), aby znaleźć najlepszą dla swoich potrzeb i wybierz jedną z nich. Na tej podstawie możesz dodawać adnotacje do encji i wdrażać DAO (lub pozwalasz Springowi zaimplementować je za Ciebie, jeśli zdecydujesz się użyć danych sprężynowych).
  5. Jeśli wymagania biznesowe ewoluują, a Twoja technologia dostępu do danych nie jest wystarczająca do ich obsługi (powiedzmy, że zacząłeś od JDBC i kilku podmiotów, ale teraz potrzebujesz bogatszego modelu danych, a JPA jest lepszym wyborem), będziesz musiał zmienić implementację swoich DAO, dodaj kilka adnotacji do swoich encji i zmień konfigurację sprężyny (dodaj definicję EntityManagerFactory). W pozostałej części kodu biznesowego zmiana nie powinna mieć innych skutków.

Uwaga: zarządzanie transakcjami

Spring udostępnia API do zarządzania transakcjami. Jeśli planujesz wykorzystać spring do dostępu do danych, powinieneś również użyć spring do zarządzania transakcjami, ponieważ bardzo dobrze się ze sobą integrują. Dla każdej technologii dostępu do danych obsługiwanej przez wiosnę istnieje dopasowany menedżer transakcji dla transakcji lokalnych lub możesz wybrać JTA, jeśli potrzebujesz transakcji rozproszonych. Wszystkie implementują to samo API, więc (po raz kolejny) wybór technologii to tylko kwestia konfiguracji, którą można zmienić bez dalszego wpływu na kod biznesowy.

Uwaga: dokumentacja sprężynowa

Odnośniki do dokumentacji Springa, o których wspomniałeś, są dość stare. Oto dokumentacja najnowszej wersji (4.1.6, obejmująca wszystkie tematy):

Spring-data nie jest częścią struktury Spring. Istnieje wspólny moduł, który należy najpierw przeczytać, aby przyzwyczaić się do zasad. Dokumentację można znaleźć tutaj:

Gaetan
źródło
Doceniam tę odpowiedź, używając terminu „parasol” w niektórych opisach tutaj (takich jak Spring Data), wskazując, że w ramach są podkomponenty / moduły (zamiast parasola, który jest bardziej specyficzny dla domeny). Wspomnienie Spring Data jest bardzo przydatne w tym kontekście, mimo że nie zostało wspomniane w pytaniu.
cellepo
Czy nie spring-jdbcoferuje innych przydatnych narzędzi, o których tutaj nie wspomniano? Na przykład uważam, że jest SimpleJdbcInsertbardzo czysty i przydatny zarówno do pojedynczego wpisu, jak i do masowego (oczywiście do rozsądnej skali).
Nom1fan
3

Wiosna DAO ( D ata ccess O bject) jest obiektem, który zapewnia abstrakcyjny interfejs do ram wdrażania JDBC czyli wiosna DAO jest uogólnione pojęcie do dostępu JDBC i Hibernate, JPA, MyBatis, używając JDO To zajęcia indywidualne Pomocy. I zapewnia uogólnioną hierarchię wyjątków poprzez zdefiniowanie adnotacji. Ta adnotacja definiuje kontener Spring do tłumaczenia wyjątków SQL z hierarchii strategii dostępu do danych i agnostycznej Springa . @RepositorySQLExceptionDataAccessException

tzn. wyjątki specyficzne dla platformy to przechwytywanie, a następnie ponowne zgłaszanie jako jeden z niesprawdzonych wyjątków dostępu do danych Springa.


Spring JDBC : W przypadku zwykłego JDBC używamy tego modułu, który jest zależny tylko od DataSourceklas szablonów, takich jak JdbcTemplate, NamedParameterJdbcTemplate(zawija JdbcTemplate) i SimpleJdbcTemplatedo zmniejszenia problemów związanych z cięciem krzyżowym.

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

}  

oraz w Spring XML:

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

Wiosna JDBC zapewnia również JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport, które stanowią wsparcie (tzn wygodny ) sposób rozszerzyć i rozwinąć własną DAO abstrakcyjny interfejs, co następuje:

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

a wiosną XML:

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

Spring ORM: W przypadku narzędzi ORM, takich jak Hibernate, JPA, MyBatis ... łatwo integruje Spring poprzez wstrzykiwanie DataSourcewraz z następującymi klasami i odpowiednimi DaoSupportklasami.

  • SessionFactory dla Hibernate
  • EntityManagerFactory dla JPA,
  • SqlSessionFactory dla MyBatis
Premraj
źródło
1

Biblioteka Spring-dao została zatrzymana w wersji 2.0.8 (styczeń 2008). Zajęcia w spring-dao zostały skopiowane do spring-tx. Tak więc, jeśli potrzebujesz klasy, którą znajdziesz w spring-dao, dodaj zamiast tego zależność do spring-tx . ( Źródło .)

Paulo Merson
źródło
0

Utworzyć interfejs jak SomeObjectDaoi tworzyć różne implementacje tego interfejsu podobnego JdbcSomeObjectDao, HibernateSomeObjectDao. Następnie w swojej SomeObjectServiceklasie będziesz operować na SomeObjectDaointerfejsie i wstrzyknąć tam jedną z konkretnych implementacji. Więc każda implementacja SomeObjectDaoukryje szczegóły, niezależnie od tego, czy używasz JDBC, czy ORM itp.

Zwykle JDBC i różne implementacje ORM generują różnego rodzaju wyjątki. Wsparcie Spring DAO może mapować te różne, specyficzne dla technologii wyjątki do typowych wyjątków Spring DAO. Więc jesteś bardziej oddzielony od rzeczywistej implementacji. Również wsparcie Springa dla DAO oferuje zestaw *DataSupportklas abstrakcyjnych , które jeszcze bardziej pomagają w rozwoju DAO. Więc oprócz implementacji SomeObjectDaointerfejsu, możesz rozszerzyć jedną z *DataSupportklas Springa .

mike_m
źródło
więc masz na myśli, że spring-dao usuwa wyjątki specyficzne dla Hibernate / JDO / JDBC i zapewnia standardowy zestaw wyjątków? Czy ma templatesdostęp do bazy danych? czy jest to tylko abstrakcja do wykorzystania z innymi komponentami sprężyn? Np. Czy jest możliwe napisanie kodu, który używa tylko spring-dao do uzyskiwania dostępu do bazy danych (bez używania spring-jdbc, spring-orm, hibernate lub jakiegokolwiek innego frameworka)?
Pat
0

Jako dodatkowe informacje. Proponuję użyć Spring Data JPA. Korzystanie z adnotacji, takich jak: @Repository, @Service. Pokażę ci przykład:

@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);

}

Gdzie CustomerEntitlementsProjection to prognoza wiosenna, powiązana z Twoim podmiotem lub DTO pojo;

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

  String getContractNumber();

  String getExecutiveNumber();
Brandon Osorio
źródło
1
Sformatuj swój kod w blokach kodu, aby był czytelny.
CertainPerformance,