Spring DAO против Spring ORM против Spring JDBC

103

Я изучал технологии доступа к данным, поддерживаемые Spring, и заметил, что в нем упоминается несколько вариантов, и я не уверен, в чем разница между ними:

Насколько я понимаю, Spring JDBC предоставляет шаблоны для сокращения шаблонного кода для доступа к базе данных простым старым способом - вы пишете свои собственные SQL-запросы.

Spring-ORM предоставляет упрощенные шаблоны для доступа к базам данных с помощью технологий ORM, таких как Hibernate, My (i) Batis и т. Д.

Spring-DAO согласно веб-сайту Spring:

Поддержка объекта доступа к данным (DAO) в Spring нацелена на упрощение последовательной работы с такими технологиями доступа к данным, как JDBC, Hibernate или JDO.

Я немного понимаю ORM и JDBC, поскольку они нацелены на разные способы доступа к БД. Но Spring-DAO просто сбивает с толку!

Может ли кто-нибудь уточнить, в чем именно разница между этими тремя? Что следует предпочесть в каких сценариях?

Также Spring-DATAдоступен еще один проект ( http://projects.spring.io/spring-data/ ). Теперь это своего рода родительский проект для всех технологий доступа к данным, поддерживаемых Spring, или это просто новое имя для Spring. -ДАО?

Пэт
источник

Ответы:

162

Вот введение в каждую упомянутую технологию.

Spring-DAO

Spring-DAO - это не модуль Spring в строгом смысле слова, а скорее соглашения, которые должны побуждать вас писать DAO и писать их хорошо. Таким образом, он не предоставляет ни интерфейсов, ни реализаций, ни шаблонов для доступа к вашим данным. При написании DAO вы должны аннотировать их, @Repositoryчтобы исключения, связанные с базовой технологией (JDBC, Hibernate, JPA и т. Д.), Последовательно транслировались в соответствующий DataAccessExceptionподкласс.

В качестве примера предположим, что теперь вы используете Hibernate, и ваш уровень сервиса «улавливает», HibernateExceptionчтобы на него реагировать. Если вы перейдете на JPA, ваши интерфейсы DAO не должны измениться, и уровень обслуживания будет по-прежнему компилироваться с блоками, которые улавливаются HibernateException, но вы никогда не войдете в эти блоки, поскольку ваши DAO теперь выбрасывают JPA PersistenceException. При использовании @Repositoryв вашем DAO исключения, связанные с базовой технологией, переводятся в Spring DataAccessException; ваш уровень обслуживания улавливает эти исключения, и если вы решите изменить технологию сохранения, DataAccessExceptionsвсе равно будет выброшен тот же Spring, так как Spring преобразовал собственные исключения.

Обратите внимание, однако, что это имеет ограниченное использование по следующим причинам:

  1. Обычно вам не следует перехватывать исключения персистентности, так как поставщик мог откатить транзакцию (в зависимости от точного подтипа исключения), и поэтому вам не следует продолжать выполнение с альтернативным путем.
  2. Иерархия исключений у вашего провайдера обычно богаче, чем у Spring, и нет окончательного сопоставления от одного провайдера к другому. Опираться на это опасно. Однако это хорошая идея для аннотирования ваших DAO @Repository, так как bean-компоненты будут автоматически добавлены процедурой сканирования. Кроме того, Spring может добавлять в аннотацию другие полезные функции.

Весна-JDBC

Spring-JDBC предоставляет класс JdbcTemplate, который удаляет соединительный код и помогает вам сосредоточиться на запросе и параметрах SQL. Вам просто нужно настроить его с помощью a DataSource, а затем вы можете написать такой код:

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 также предоставляет поддержку JdbcDaoSupport, которую вы можете расширить для разработки своего DAO. Он в основном определяет 2 свойства: DataSource и JdbcTemplate, которые можно использовать для реализации методов DAO. Он также предоставляет преобразователь исключений из исключений SQL в Spring DataAccessExceptions.

Если вы планируете использовать простой jdbc, вам понадобится именно этот модуль.

Spring-ORM

Spring-ORM - это зонтичный модуль, охватывающий многие технологии сохранения, а именно JPA, JDO, Hibernate и iBatis. Для каждой из этих технологий Spring предоставляет классы интеграции, так что каждую технологию можно использовать в соответствии с принципами настройки Spring и плавно интегрировать с управлением транзакциями Spring.

Для каждой технологии конфигурация в основном заключается во внедрении DataSourcebean-компонента в какой-либо SessionFactoryили EntityManagerFactoryт. Д. Bean-компонент. Для чистого JDBC нет необходимости в таких классах интеграции (кроме JdbcTemplate), поскольку JDBC полагается только на DataSource.

Если вы планируете использовать ORM, например JPA или Hibernate, вам не понадобится spring-jdbc, а только этот модуль.

Spring-Data

Spring-Data - это зонтичный проект, который предоставляет общий API для определения того, как получить доступ к данным (аннотации DAO +) более общим способом, охватывающим как источники данных SQL, так и NOSQL.

Первоначальная идея состоит в том, чтобы предоставить технологию, чтобы разработчик писал интерфейс для DAO (методы поиска) и классы сущностей независимым от технологии способом и, основываясь только на конфигурации (аннотации к DAO и сущностям + конфигурация Spring, будь то xml или java), определяет технологию реализации, будь то JPA (SQL) или redis, hadoop и т. д. (NOSQL).

Если вы следуете соглашениям об именах, определенным spring для имен методов поиска, вам даже не нужно предоставлять строки запроса, соответствующие методам поиска, для самых простых случаев. В других случаях вы должны предоставить строку запроса внутри аннотаций методов поиска.

Когда контекст приложения загружен, spring предоставляет прокси для интерфейсов DAO, которые содержат весь шаблонный код, связанный с технологией доступа к данным, и вызывает настроенные запросы.

Spring-Data концентрируется на технологиях, отличных от SQL, но по-прежнему предоставляет модуль для JPA (единственная технология SQL).

Что дальше

Зная все это, вы должны решить, что выбрать. Хорошая новость заключается в том, что вам не нужно делать окончательный выбор в пользу технологии. Именно в этом и заключается сила Spring: как разработчик вы сосредотачиваетесь на бизнесе, когда пишете код, и, если вы делаете это хорошо, изменение базовой технологии - это деталь реализации или конфигурации.

  1. Определите модель данных с классами POJO для сущностей и методами получения / установки для представления атрибутов сущностей и отношений с другими сущностями. Вам, безусловно, нужно будет аннотировать классы и поля сущностей в зависимости от технологии, но пока для начала достаточно POJO. Просто сконцентрируйтесь на бизнес-требованиях.
  2. Определите интерфейсы для ваших DAO. 1 DAO охватывает ровно 1 объект, но вам определенно не понадобится DAO для каждого из них, поскольку вы должны иметь возможность загружать дополнительные объекты, перемещаясь по отношениям. Определите методы поиска, следуя строгим соглашениям об именах.
  3. Исходя из этого, кто-то другой может начать работу над уровнем сервисов с макетами для ваших DAO.
  4. Вы изучаете различные технологии персистентности (sql, no-sql), чтобы найти наиболее подходящие для ваших нужд, и выбираете одну из них. На основе этого вы аннотируете сущности и реализуете DAO (или позволяете Spring реализовать их за вас, если вы решите использовать данные spring).
  5. Если бизнес-требования развиваются и ваша технология доступа к данным недостаточна для их поддержки (скажем, вы начали с JDBC и нескольких сущностей, но теперь вам нужна более богатая модель данных, а JPA - лучший выбор), вам придется изменить реализацию ваших DAO, добавьте несколько аннотаций к своим сущностям и измените конфигурацию Spring (добавьте определение EntityManagerFactory). Остальная часть вашего бизнес-кода не должна иметь других последствий от вашего изменения.

Примечание: управление транзакциями

Spring предоставляет API для управления транзакциями. Если вы планируете использовать Spring для доступа к данным, вам также следует использовать Spring для управления транзакциями, поскольку они очень хорошо интегрируются друг с другом. Для каждой технологии доступа к данным, поддерживаемой spring, существует соответствующий менеджер транзакций для локальных транзакций, или вы можете выбрать JTA, если вам нужны распределенные транзакции. Все они реализуют один и тот же API, так что (еще раз) выбор технологии - это всего лишь вопрос конфигурации, которую можно изменить без дальнейшего воздействия на бизнес-код.

Примечание: документация Spring

Упомянутые вами ссылки на документацию Spring довольно старые. Вот документация к последней версии (4.1.6, охватывающей все темы):

Spring-data не является частью среды Spring. Существует общий модуль, который вам следует сначала прочитать, чтобы привыкнуть к принципам. Документацию можно найти здесь:

Гаэтан
источник
Я ценю этот ответ, используя термин «зонтик» в некоторых описаниях здесь (например, Spring Data), определяя, что внутри есть подкомпоненты / модули (а не зонтик, более специфичный для домена). И упоминание Spring Data здесь очень полезно в контексте, даже если оно не упоминалось в вопросе.
cellepo 06
Не spring-jdbcпредоставляет другие полезные инструменты, не упомянутые здесь? Например, я считаю SimpleJdbcInsertочень чистым и полезным как для однократной, так и для массовой вставки (до разумного масштаба, конечно).
Nom1fan
3

Spring DAO ( D ата ступа O ▪ Таблица): это объект , который предоставляет абстрактный интерфейс для рамок реализации JDBC , т.е. Spring DAO является обобщенным понятием для доступа JDBC и Hibernate, MyBatis, JPA, JDO , используя его отдельные классы поддержки. И он обеспечивает обобщенную иерархию исключений, определяя аннотацию. Эта аннотация определяет контейнер Spring для преобразования исключений SQL из в иерархию Spring, не зависящую от стратегии доступа к данным . @RepositorySQLExceptionDataAccessException

то есть, специфичные для платформы исключения - это перехват, а затем повторный выброс как одно из исключений доступа к неконтролируемым данным Spring.


Spring JDBC : Для простого JDBC мы используем этот модуль, который зависит только от DataSourceи шаблонных классов нравятся JdbcTemplate, NamedParameterJdbcTemplate(компрессы JdbcTemplate) и SimpleJdbcTemplateдля уменьшения перекрестных проблем резания.

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

}  

и в Spring XML:

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

Spring JDBC также JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport, которые являются поддержка (т.е. удобный ) способ расширить и развить свой собственный DAO абстрактный интерфейс следующим образом :

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

а весной XML:

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

Spring ORM: для поддержки инструментов ORM, таких как Hibernate, JPA, MyBatis ... легко интегрирует Spring путем внедрения DataSourceвместе со следующими классами и соответствующими DaoSupportклассами.

  • SessionFactory для гибернации
  • EntityManagerFactory для JPA,
  • SqlSessionFactory для MyBatis
Премрадж
источник
1

Spring-dao lib остановлен в версии 2.0.8 (январь 2008 г.). Классы spring-dao были скопированы в spring-tx. Итак, если вам нужен класс, который вы найдете в spring-dao, вместо этого добавьте зависимость к spring-tx . ( Источник .)

Пауло Мерсон
источник
0

Вы можете создать интерфейс , как SomeObjectDaoи затем создавать различные реализации этого интерфейса , как JdbcSomeObjectDao, HibernateSomeObjectDao. Затем в своем SomeObjectServiceклассе вы будете работать с SomeObjectDaoинтерфейсом и внедрить туда одну из конкретных реализаций. Таким образом, каждая реализация SomeObjectDaoбудет скрывать детали, независимо от того, используете ли вы JDBC или ORM и т. Д.

Обычно JDBC и разные реализации ORM выдают разные исключения. Поддержка Spring DAO может сопоставить эти разные, специфичные для технологии исключения, с общими исключениями Spring DAO. Таким образом, вы больше не связаны с реальной реализацией. Также поддержка Spring DAO предлагает набор абстрактных *DataSupportклассов, которые еще больше помогают в разработке DAO. Итак, помимо реализации вашего SomeObjectDaoинтерфейса, вы можете расширить один из *DataSupportклассов Spring .

mike_m
источник
значит, вы имеете в виду, что spring-dao абстрагирует исключения, специфичные для Hibernate / JDO / JDBC, и предоставляет стандартный набор исключений? Есть ли у него templatesдоступ к БД? или это просто абстракция для использования с другими компонентами Spring? Например, можно ли написать код, который использует только spring-dao для доступа к db (без использования spring-jdbc, spring-orm, hibernate или любой другой структуры)?
Пэт
0

В качестве дополнительной информации. Я предлагаю вам использовать Spring Data JPA. Использование аннотаций, таких как: @Repository, @Service. Я показываю вам пример:

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

}

Где CustomerEntitlementsProjection - это проекция Spring, связанная с вашей сущностью или DTO pojo;

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

  String getContractNumber();

  String getExecutiveNumber();
Брэндон Осорио
источник
1
Пожалуйста, отформатируйте свой код в блоках кода, чтобы его можно было читать.
CertainPerformance