Spring DAO vs Spring ORM vs Spring JDBC

103

Eu estava passando por tecnologias de acesso a dados suportadas pelo Spring e percebi que ele menciona várias opções e não tenho certeza sobre a diferença entre elas:

Pelo que entendi, Spring JDBC fornece modelos para reduzir o código clichê para acessar um banco de dados da maneira antiga - você escreve suas próprias consultas SQL.

Spring-ORM fornece modelos simplificados para acessar bancos de dados através de tecnologias ORM, como Hibernate, My (i) Batis etc.

Spring-DAO de acordo com o site da Spring:

O suporte a Data Access Object (DAO) no Spring visa facilitar o trabalho com tecnologias de acesso a dados como JDBC, Hibernate ou JDO de uma maneira consistente

Estou um pouco claro sobre ORM vs JDBC, pois eles visam maneiras diferentes de acessar o banco de dados. Mas Spring-DAO é simplesmente confuso!

Alguém poderia esclarecer quais são exatamente as diferenças entre esses três? Qual deve ser preferido em quais cenários?

Além disso, há outro projeto Spring-DATAtambém disponível ( http://projects.spring.io/spring-data/ ) Agora, é uma espécie de projeto pai para todos os técnicos de acesso a dados suportados pelo Spring ou é apenas um novo nome para Spring -DAO?

Pat
fonte

Respostas:

162

Aqui está uma introdução a cada tecnologia mencionada.

Spring-DAO

Spring-DAO não é um módulo spring em um sentido estrito, mas sim convenções que deveriam ditar que você deve escrever DAO, e bem. Como tal, ele não fornece interfaces, nem implementações, nem modelos para acessar seus dados. Ao escrever um DAO, você deve anotá-los @Repositorypara que as exceções vinculadas à tecnologia subjacente (JDBC, Hibernate, JPA, etc.) sejam consistentemente traduzidas na DataAccessExceptionsubclasse adequada .

Por exemplo, suponha que você agora esteja usando o Hibernate e sua camada de serviço seja travada HibernateExceptionpara reagir a ele. Se você mudar para JPA, as interfaces de seus DAOs não deverão mudar e a camada de serviço ainda será compilada com blocos capturados HibernateException, mas você nunca entrará nesses blocos, pois seus DAOs agora estão lançando JPA PersistenceException. Ao usar @Repositoryem seu DAO, as exceções vinculadas à tecnologia subjacente são traduzidas para Spring DataAccessException; sua camada de serviço captura essas exceções e se você decidir mudar a tecnologia de persistência, o mesmo Spring DataAccessExceptionsainda será lançado, pois o spring traduziu exceções nativas.

Observe, entretanto, que isso tem uso limitado pelos seguintes motivos:

  1. Normalmente, você não deve capturar exceções de persistência, pois o provedor pode ter revertido a transação (dependendo do subtipo de exceção exato) e, portanto, você não deve continuar a execução com um caminho alternativo.
  2. A hierarquia de exceções geralmente é mais rica em seu provedor do que a fornecida pelo Spring, e não há mapeamento definitivo de um provedor para outro. Depender disso é perigoso. No entanto, é uma boa ideia fazer anotações em seus DAOs @Repository, pois os beans serão adicionados automaticamente pelo procedimento de varredura. Além disso, o Spring pode adicionar outros recursos úteis à anotação.

Spring-JDBC

Spring-JDBC fornece a classe JdbcTemplate, que remove o código do encanamento e ajuda você a se concentrar na consulta SQL e nos parâmetros. Você só precisa configurá-lo com um DataSource, e você pode escrever o código como este:

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 também fornece um JdbcDaoSupport, que você pode estender para desenvolver seu DAO. Ele basicamente define 2 propriedades: um DataSource e um JdbcTemplate que podem ser usados ​​para implementar os métodos DAO. Ele também fornece um tradutor de exceções de exceções SQL para spring DataAccessExceptions.

Se você planeja usar jdbc simples, este é o módulo que você precisará usar.

Spring-ORM

Spring-ORM é um módulo abrangente que cobre muitas tecnologias de persistência, a saber JPA, JDO, Hibernate e iBatis. Para cada uma dessas tecnologias, o Spring fornece classes de integração para que cada tecnologia possa ser usada seguindo os princípios de configuração do Spring e se integre perfeitamente ao gerenciamento de transações do Spring.

Para cada uma das tecnologias, a configuração basicamente consiste na injecção de um DataSourcefeijão em algum tipo de SessionFactoryou EntityManagerFactoryetc feijão. Para JDBC puro, não há necessidade de tais classes de integração (além do JdbcTemplate), já que o JDBC depende apenas de um DataSource.

Se você planeja usar um ORM como JPA ou Hibernate, não precisará do spring-jdbc, mas apenas deste módulo.

Spring-Data

Spring-Data é um projeto abrangente que fornece uma API comum para definir como acessar dados (anotações DAO +) de uma forma mais genérica, abrangendo fontes de dados SQL e NOSQL.

A ideia inicial é fornecer uma tecnologia para que o desenvolvedor escreva a interface para um DAO (métodos de localização) e as classes de entidade de uma forma agnóstica de tecnologia e, com base apenas na configuração (anotações em DAOs e entidades + configuração de mola, seja baseado em xml ou java), decide a tecnologia de implementação, seja JPA (SQL) ou redis, hadoop, etc. (NOSQL).

Se você seguir as convenções de nomenclatura definidas pelo spring para os nomes dos métodos do localizador, você nem mesmo precisa fornecer as strings de consulta correspondentes aos métodos do localizador para os casos mais simples. Para outras situações, você deve fornecer a string de consulta dentro das anotações nos métodos localizadores.

Quando o contexto do aplicativo é carregado, o spring fornece proxies para as interfaces DAO, que contêm todo o código clichê relacionado à tecnologia de acesso a dados, e invoca as consultas configuradas.

Spring-Data concentra-se em tecnologias não SQL, mas ainda fornece um módulo para JPA (a única tecnologia SQL).

Qual é o próximo

Sabendo de tudo isso, você agora precisa decidir o que escolher. A boa notícia aqui é que você não precisa fazer uma escolha final definitiva para a tecnologia. Na verdade, é aqui que reside o poder do Spring: como desenvolvedor, você se concentra no negócio ao escrever o código e, se o fizer bem, mudar a tecnologia subjacente é um detalhe de implementação ou configuração.

  1. Defina um modelo de dados com classes POJO para as entidades e métodos get / set para representar os atributos da entidade e os relacionamentos com outras entidades. Você certamente precisará anotar as classes de entidade e os campos com base na tecnologia, mas por enquanto, os POJOs são suficientes para começar. Apenas concentre-se nos requisitos de negócios por enquanto.
  2. Defina interfaces para seus DAOs. 1 DAO cobre exatamente 1 entidade, mas você certamente não precisará de um DAO para cada uma delas, pois você deve ser capaz de carregar entidades adicionais navegando pelos relacionamentos. Defina os métodos de localização seguindo convenções de nomenclatura rígidas.
  3. Com base nisso, outra pessoa pode começar a trabalhar na camada de serviços, com simulações para seus DAOs.
  4. Você aprende as diferentes tecnologias de persistência (sql, no-sql) para encontrar a que melhor se adapta às suas necessidades e escolhe uma delas. Com base nisso, você anota as entidades e implementa os DAOs (ou permite que o spring os implemente para você se você escolher usar o spring-data).
  5. Se os requisitos de negócios evoluírem e sua tecnologia de acesso a dados não for suficiente para suportá-los (digamos, você começou com JDBC e algumas entidades, mas agora precisa de um modelo de dados mais rico e JPA é uma escolha melhor), você terá que alterar a implementação de seus DAOs, adicione algumas anotações em suas entidades e altere a configuração da mola (adicione uma definição EntityManagerFactory). O resto do seu código de negócios não deve ver outros impactos de sua mudança.

Nota: Gestão de transações

Spring fornece uma API para gerenciamento de transações. Se você planeja usar o spring para o acesso aos dados, você também deve usar o spring para o gerenciamento de transações, pois eles se integram muito bem. Para cada tecnologia de acesso a dados suportada pela primavera, há um gerenciador de transações correspondente para transações locais, ou você pode escolher JTA se precisar de transações distribuídas. Todos eles implementam a mesma API, de forma que (mais uma vez) a escolha da tecnologia seja apenas uma questão de configuração que pode ser alterada sem maior impacto no código de negócios.

Nota: documentação do Spring

Os links para a documentação do Spring que você mencionou são bastante antigos. Aqui está a documentação da versão mais recente (4.1.6, cobrindo todos os tópicos):

Spring-data não faz parte da estrutura Spring. Existe um módulo comum que você deve ler primeiro para se acostumar com os princípios. A documentação pode ser encontrada aqui:

Gaetan
fonte
Eu aprecio esta resposta usando o termo "guarda-chuva" em algumas descrições aqui (como Spring Data), identificando que há subcomponentes / módulos dentro (ao invés de um guarda-chuva sendo mais específico do domínio). E mencionar Spring Data é muito útil no contexto aqui, embora não tenha sido mencionado na pergunta.
cellepo
Não spring-jdbcfornece outras ferramentas úteis não mencionadas aqui? Por exemplo, considero SimpleJdbcInsertmuito simples e útil tanto para inserção de entrada única quanto em massa (até uma escala razoável, é claro).
Nom1fan
3

Mola DAO ( D ATA Um cesso S bject): é um objecto que fornece uma interface resumo para as estruturas de aplicação JDBC ie mola DAO é generalizada conceito para acesso JDBC e de hibernação, MyBatis, APP, JDO utilizando TI de classes de suporte individuais. E fornece hierarquia de exceção generalizada definindo @Repositoryanotação. Esta anotação define o contêiner do Spring para a conversão da exceção SQL da hierarquia SQLExceptionagnóstica de estratégia de acesso a dados do Spring DataAccessException.

ou seja, as exceções específicas da plataforma são capturadas e, em seguida, lançadas novamente como uma das exceções não verificadas de acesso a dados do Spring.


Spring JDBC : Para JDBC simples, usamos este módulo, que depende apenas de DataSourceclasses de Template como JdbcTemplate, NamedParameterJdbcTemplate(wraps JdbcTemplate) e SimpleJdbcTemplatepara reduzir questões de corte cruzado.

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 em Spring XML:

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

Primavera JDBC também fornece JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport, que são suporte (ou seja conveniente ) maneira de ampliar e desenvolver o nosso próprio DAO interface abstrata da seguinte forma:

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 na primavera XML:

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

Spring ORM: Para suporte a ferramentas ORM como Hibernate, JPA, MyBatis ... integra-se facilmente ao Spring injetando DataSourcejunto com as seguintes classes e respectivas DaoSupportclasses.

  • SessionFactory para Hibernate
  • EntityManagerFactory para JPA,
  • SqlSessionFactory para MyBatis
Premraj
fonte
1

A lib spring-dao parou na versão 2.0.8 (janeiro de 2008). As aulas em spring-dao foram copiadas para spring-tx. Portanto, se você precisar de uma classe que encontra em spring-dao, adicione a dependência a spring-tx . ( Fonte .)

Paulo Merson
fonte
0

Você cria interface como SomeObjectDaoe, em seguida, criar diferentes implementações dessa interface como JdbcSomeObjectDao, HibernateSomeObjectDao. Então, em sua SomeObjectServiceaula, você irá operar a SomeObjectDaointerface e injetar ali uma das implementações concretas. Portanto, cada implementação de SomeObjectDaoocultará os detalhes, se você usar JDBC ou ORM etc.

Normalmente JDBC e diferentes implementações de ORM lançam diferentes tipos de exceções. O suporte a DAO do Spring pode mapear essas diferentes exceções específicas de tecnologia para exceções comuns do Spring DAO. Portanto, você está mais desacoplado da implementação real. Além disso, o suporte a DAO do Spring oferece um conjunto de *DataSupportclasses abstratas que ajudam ainda mais no desenvolvimento de DAO. Portanto, além de implementar sua SomeObjectDaointerface, você pode estender uma das *DataSupportclasses do Spring .

mike_m
fonte
então você quer dizer, spring-dao abstrai exceções específicas para Hibernate / JDO / JDBC e fornece um conjunto padrão de exceções? Tem algum templatespara acessar db? ou é apenas uma abstração para ser usada com outros componentes da mola? Por exemplo, é possível escrever código que usa apenas spring-dao para acessar db (sem usar spring-jdbc, spring-orm, hibernate ou qualquer outro framework)?
Pat
0

Como informação adicional. Eu sugiro que você use Spring Data JPA. Usando anotações como: @Repository, @Service. Eu te mostro um exemplo:

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

}

Onde CustomerEntitlementsProjection é a projeção Spring, vinculada à sua entidade ou DTO pojo;

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

  String getContractNumber();

  String getExecutiveNumber();
Brandon Osorio
fonte
1
Formate seu código em blocos de código para que seja legível.
CertainPerformance