Spring DAO vs Spring ORM vs Spring JDBC

103

Estaba pasando por tecnologías de acceso a datos compatibles con Spring, y noté que menciona múltiples opciones y no estoy seguro de la diferencia entre ellas:

Según tengo entendido, Spring JDBC proporciona plantillas para reducir el código repetitivo para acceder a una base de datos a través de la forma antigua: usted escribe sus propias consultas SQL.

Spring-ORM proporciona plantillas simplificadas para acceder a bases de datos a través de tecnologías ORM, como Hibernate, My (i) Batis, etc.

Spring-DAO según el sitio web de Spring:

La compatibilidad con objetos de acceso a datos (DAO) en Spring tiene como objetivo facilitar el trabajo con tecnologías de acceso a datos como JDBC, Hibernate o JDO de manera coherente

Tengo un poco claro acerca de ORM vs JDBC, ya que están dirigidos a diferentes formas de acceder a la base de datos. ¡Pero Spring-DAO es simplemente confuso!

¿Alguien podría aclarar cuáles son exactamente las diferencias entre estos tres? ¿Cuál debería preferirse en qué escenarios?

Además, también hay otro proyecto Spring-DATAdisponible ( http://projects.spring.io/spring-data/ ) Ahora, ¿es una especie de proyecto principal para todos los técnicos de acceso a datos admitidos por Spring o es solo un nuevo nombre para Spring? -DAO?

Palmadita
fuente

Respuestas:

162

Aquí hay una introducción a cada tecnología mencionada.

Primavera-DAO

Spring-DAO no es un módulo de primavera en un sentido estricto, sino más bien convenciones que deberían dictarle que escriba DAO y que las escriba bien. Como tal, no proporciona interfaces, implementaciones ni plantillas para acceder a sus datos. Al escribir un DAO, debe anotarlos @Repositorypara que las excepciones vinculadas a la tecnología subyacente (JDBC, Hibernate, JPA, etc.) se traduzcan consistentemente en la DataAccessExceptionsubclase adecuada .

Como ejemplo, suponga que ahora está utilizando Hibernate, y su capa de servicio detecta HibernateExceptionpara reaccionar. Si cambia a JPA, las interfaces de su DAO no deberían cambiar y la capa de servicio aún se compilará con los bloques que detecta HibernateException, pero nunca ingresará estos bloques ya que sus DAO ahora están lanzando JPA PersistenceException. Al usarlo @Repositoryen su DAO, las excepciones vinculadas a la tecnología subyacente se traducen a Spring DataAccessException; su capa de servicio detecta estas excepciones y si decide cambiar la tecnología de persistencia, el mismo Spring DataAccessExceptionstodavía se lanzará ya que Spring ha traducido excepciones nativas.

Sin embargo, tenga en cuenta que esto tiene un uso limitado por las siguientes razones:

  1. Por lo general, no debe detectar excepciones de persistencia, ya que el proveedor puede haber revertido la transacción (según el subtipo de excepción exacto) y, por lo tanto, no debe continuar la ejecución con una ruta alternativa.
  2. La jerarquía de excepciones suele ser más rica en su proveedor que la que proporciona Spring, y no hay un mapeo definitivo de un proveedor a otro. Confiar en esto es peligroso. Sin embargo, esta es una buena idea para anotar sus DAO @Repository, ya que el procedimiento de escaneo agregará automáticamente los beans. Además, Spring puede agregar otras características útiles a la anotación.

Spring-JDBC

Spring-JDBC proporciona la clase JdbcTemplate, que elimina el código de plomería y lo ayuda a concentrarse en la consulta y los parámetros SQL. Solo necesita configurarlo con a DataSource, y luego puede escribir 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 también proporciona un JdbcDaoSupport, que puede ampliar para desarrollar su DAO. Básicamente define 2 propiedades: un DataSource y un JdbcTemplate que ambos pueden usarse para implementar los métodos DAO. También proporciona un traductor de excepciones de excepciones SQL a Spring DataAccessExceptions.

Si planea usar jdbc simple, este es el módulo que necesitará usar.

Primavera-ORM

Spring-ORM es un módulo general que cubre muchas tecnologías de persistencia, a saber, JPA, JDO, Hibernate e iBatis. Para cada una de estas tecnologías, Spring proporciona clases de integración para que cada tecnología se pueda utilizar siguiendo los principios de configuración de Spring y se integre sin problemas con la gestión de transacciones de Spring.

Para cada tecnología, la configuración básicamente consiste en inyectar un DataSourcebean en una especie de SessionFactoryo EntityManagerFactoryetc. bean. Para JDBC puro, no hay necesidad de tales clases de integración (aparte de JdbcTemplate), ya que JDBC solo se basa en un DataSource.

Si planea usar un ORM como JPA o Hibernate, no necesitará spring-jdbc, sino solo este módulo.

Spring-Data

Spring-Data es un proyecto general que proporciona una API común para definir cómo acceder a los datos (anotaciones DAO +) de una manera más genérica, cubriendo fuentes de datos SQL y NOSQL.

La idea inicial es proporcionar una tecnología para que el desarrollador escriba la interfaz para un DAO (métodos de búsqueda) y las clases de entidad de una manera agnóstica a la tecnología y, basándose únicamente en la configuración (anotaciones en DAOs y entidades + configuración de primavera, ya sea xml o basado en java), decide la tecnología de implementación, ya sea JPA (SQL) o redis, hadoop, etc. (NOSQL).

Si sigue las convenciones de nomenclatura definidas por Spring para los nombres de los métodos del buscador, ni siquiera necesita proporcionar las cadenas de consulta correspondientes a los métodos del buscador para los casos más simples. Para otras situaciones, debe proporcionar la cadena de consulta dentro de las anotaciones en los métodos del buscador.

Cuando se carga el contexto de la aplicación, Spring proporciona proxies para las interfaces DAO, que contienen todo el código repetitivo relacionado con la tecnología de acceso a datos, e invoca las consultas configuradas.

Spring-Data se concentra en tecnologías que no son SQL, pero aún proporciona un módulo para JPA (la única tecnología SQL).

Que sigue

Sabiendo todo esto, ahora debes decidir qué elegir. La buena noticia aquí es que no necesita tomar una decisión final definitiva para la tecnología. Aquí es donde reside el poder de Spring: como desarrollador, usted se concentra en el negocio cuando escribe código y, si lo hace bien, cambiar la tecnología subyacente es un detalle de implementación o configuración.

  1. Defina un modelo de datos con clases POJO para las entidades y métodos get / set para representar los atributos de la entidad y las relaciones con otras entidades. Sin duda, necesitará anotar las clases de entidad y los campos según la tecnología, pero por ahora, los POJO son suficientes para empezar. Solo concéntrese en los requisitos comerciales por ahora.
  2. Defina interfaces para sus DAO. 1 DAO cubre exactamente 1 entidad, pero ciertamente no necesitará un DAO para cada una de ellas, ya que debería poder cargar entidades adicionales navegando por las relaciones. Defina los métodos del buscador siguiendo estrictas convenciones de nomenclatura.
  3. En base a esto, alguien más puede comenzar a trabajar en la capa de servicios, con simulaciones para sus DAO.
  4. Aprende las diferentes tecnologías de persistencia (sql, no-sql) para encontrar la que mejor se adapta a sus necesidades y elige una de ellas. En base a esto, anote las entidades e implemente los DAO (o deje que Spring las implemente por usted si elige usar Spring-Data).
  5. Si los requisitos comerciales evolucionan y su tecnología de acceso a datos no es suficiente para respaldarlos (digamos, comenzó con JDBC y algunas entidades, pero ahora necesita un modelo de datos más rico y JPA es una mejor opción), tendrá que cambiar la implementación de sus DAO, agregue algunas anotaciones en sus entidades y cambie la configuración del resorte (agregue una definición de EntityManagerFactory). El resto de su código comercial no debería ver otros impactos de su cambio.

Nota: Gestión de transacciones

Spring proporciona una API para la gestión de transacciones. Si planea usar Spring para el acceso a los datos, también debe usar Spring para la gestión de transacciones, ya que se integran muy bien. Para cada tecnología de acceso a datos compatible con Spring, hay un administrador de transacciones coincidente para transacciones locales, o puede elegir JTA si necesita transacciones distribuidas. Todos ellos implementan la misma API, por lo que (una vez más) la elección de la tecnología es solo una cuestión de una configuración que se puede cambiar sin mayor impacto en el código comercial.

Nota: documentación de Spring

Los enlaces a la documentación de Spring que mencionaste son bastante antiguos. Aquí está la documentación de la última versión (4.1.6, que cubre todos los temas):

Spring-data no es parte del marco de Spring. Hay un módulo común que debe leer primero para acostumbrarse a los principios. La documentación se puede encontrar aquí:

Gaetan
fuente
Aprecio que esta Respuesta use el término "paraguas" en algunas descripciones aquí (como Spring Data), identificando que hay subcomponentes / módulos dentro (en lugar de un paraguas que sea más específico del dominio). Y mencionar Spring Data es muy útil en contexto aquí, aunque no se mencionó en la pregunta.
cellepo
¿No spring-jdbcproporciona otras herramientas útiles que no se mencionan aquí? Por ejemplo, me parece SimpleJdbcInsertmuy limpio y útil tanto para la inserción de una sola entrada como para el volumen (hasta una escala razonable, por supuesto).
Nom1fan
3

Primavera DAO ( D ata A cceso O bject): es un objeto que proporciona una interfaz abstracta para marcos de aplicación JDBC, es decir, la primavera DAO se generaliza el concepto de acceso JDBC y Hibernate, MyBatis, JPA, JDO utilizando su clases de apoyo individuales. Y proporciona una jerarquía de excepciones generalizada al definir la @Repositoryanotación. Esta anotación define el contenedor Spring para la traducción de excepciones SQL desde SQLExceptionla DataAccessExceptionjerarquía independiente de la estrategia de acceso a datos de Spring .

es decir, las excepciones específicas de la plataforma son capturas y luego relanzamientos como una de las excepciones de acceso a datos no controladas de Spring.


Spring JDBC : para JDBC simple usamos este módulo, que solo depende de DataSourceclases de plantilla como JdbcTemplate, NamedParameterJdbcTemplate(envolturas JdbcTemplate) y SimpleJdbcTemplatepara reducir preocupaciones transversales.

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

}  

y en Spring XML:

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

Primavera JDBC también proporciona JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport, que son de apoyo (es decir conveniente ) manera de ampliar y desarrollar nuestra propia DAO interfaz abstracta de la siguiente manera:

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

y en primavera XML:

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

Spring ORM: Para soporte de herramientas ORM como Hibernate, JPA, MyBatis ... integra fácilmente Spring inyectando DataSourcejunto con las siguientes clases y DaoSupportclases respectivas .

  • SessionFactory para hibernar
  • EntityManagerFactory para JPA,
  • SqlSessionFactory para MyBatis
Premraj
fuente
1

Spring-dao lib se detuvo en la versión 2.0.8 (enero de 2008). Las clases de spring-dao se copiaron a spring-tx. Entonces, si necesita una clase que encuentre en spring-dao, agregue la dependencia a spring-tx en su lugar. ( Fuente .)

Paulo Merson
fuente
0

Se crea como el interfaz SomeObjectDaoy luego crear diferentes implementaciones de esta interfaz como JdbcSomeObjectDao, HibernateSomeObjectDao. Luego, en su SomeObjectServiceclase, operará en la SomeObjectDaointerfaz e inyectará allí una de las implementaciones concretas. Por lo tanto, cada implementación de SomeObjectDaoocultará los detalles, ya sea que use JDBC u ORM, etc.

Por lo general, JDBC y diferentes implementaciones de ORM arrojan diferentes tipos de excepciones. El soporte DAO de Spring puede asignar esas excepciones específicas de tecnología diferentes a las excepciones DAO comunes de Spring. Por lo que está más desacoplado de la implementación real. Además, el soporte DAO de Spring ofrece un conjunto de *DataSupportclases abstractas que ayudan aún más en el desarrollo de DAO. Entonces, además de implementar su SomeObjectDaointerfaz, puede extender una de las *DataSupportclases de Spring .

mike_m
fuente
Entonces, ¿quieres decir que spring-dao abstrae las excepciones específicas de Hibernate / JDO / JDBC y proporciona un conjunto estándar de excepciones? ¿Tiene alguno templatespara acceder a la base de datos? ¿O es solo una abstracción para usar con otros componentes de resorte? Por ejemplo, ¿es posible escribir código que use solo spring-dao para acceder a db (sin usar spring-jdbc, spring-orm, hibernate o cualquier otro marco)?
Pat
0

Como información adicional. Le sugiero que use Spring Data JPA. Usando anotaciones como: @Repository, @Service. Te muestro un ejemplo:

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

}

Donde CustomerEntitlementsProjection es la proyección Spring, vinculada con su entidad o pojo DTO;

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

  String getContractNumber();

  String getExecutiveNumber();
Brandon Osorio
fuente
1
Formatee su código en bloques de código para que sea legible.
CertainPerformance