Spring DAO vs Spring ORM vs Spring JDBC

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24990400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 06:51:30  来源:igfitidea点击:

Spring DAO vs Spring ORM vs Spring JDBC

springspring-dataspring-jdbcspring-orm

提问by Pat

I was going through data access technologies supported by Spring, and I noticed that it mentions multiple options and I am not sure about the difference among them:

我正在研究 Spring 支持的数据访问技术,我注意到它提到了多个选项,我不确定它们之间的区别:

As I understand, Spring JDBC provides templates for reducing boilerplate code for accessing a database through plain old way - you write your own SQL queries.

据我了解,Spring JDBC 提供了用于减少样板代码以通过简单的旧方式访问数据库的模板 - 您编写自己的 SQL 查询。

Spring-ORM provides simplified templates for accessing databases through ORM technologies, such as Hibernate, My(i)Batis etc.

Spring-ORM 提供了通过 ORM 技术访问数据库的简化模板,例如 Hibernate、My(i)Batis 等。

Spring-DAO as per Spring's website:

Spring-DAO 根据 Spring 的网站:

The Data Access Object (DAO) support in Spring is aimed at making it easy to work with data access technologies like JDBC, Hibernate or JDO in a consistent way

Spring 中的数据访问对象 (DAO) 支持旨在以一致的方式轻松使用 JDBC、Hibernate 或 JDO 等数据访问技术

I am a bit clear about ORM vs JDBC as they are aimed at different ways of accessing the DB. But Spring-DAO is just plain confusing!

我对 ORM 与 JDBC 有点清楚,因为它们针对不同的访问数据库的方式。但是 Spring-DAO 简直令人困惑!

Could anyone please clarify what exactly are the differences among these three? Which should be preferred in which scenarios?

任何人都可以澄清这三者之间究竟有什么区别?在哪些情况下应该优先选择哪个?

Also, there is another project Spring-DATAalso available (http://projects.spring.io/spring-data/) Now, is it kind of a parent project for all data access techs supported by Spring or is it just a new name for Spring-DAO?

此外,还有另一个项目Spring-DATAhttp://projects.spring.io/spring-data/)现在,它是 Spring 支持的所有数据访问技术的父项目,还是只是 Spring 的一个新名称-DAO?

回答by Gaetan

Here is an introduction to each mentioned technology.

以下是对每项提到的技术的介绍。

Spring-DAO

Spring-DAO

Spring-DAO is not a spring module in a strict sense, but rather conventions that should dictate you to write DAO, and to write them well. As such, it does neither provide interfaces nor implementations nor templates to access your data. When writing a DAO, you should annotate them with @Repositoryso that exceptions linked to the underlying technology (JDBC, Hibernate, JPA, etc.) are consistently translated into the proper DataAccessExceptionsubclass.

Spring-DAO 不是严格意义上的 spring 模块,而是应该指示您编写 DAO 并写好它们的约定。因此,它既不提供接口、实现或模板来访问您的数据。在编写 DAO 时,您应该对它们进行注释,@Repository以便将与底层技术(JDBC、Hibernate、JPA 等)相关联的异常一致地转换为正确的DataAccessException子类。

As an example, suppose you're now using Hibernate, and your service layer catches HibernateExceptionin order to react to it. If you change to JPA, your DAOs interfaces should not change, and the service layer will still compile with blocks that catches HibernateException, but you will never enter these blocks as your DAOs are now throwing JPA PersistenceException. By using @Repositoryon your DAO, the exceptions linked to the underlying technology are translated to Spring DataAccessException; your service layer catches these exceptions and if you decide to change the persistence technology, the same Spring DataAccessExceptionswill still be thrown as spring have translated native exceptions.

例如,假设您现在正在使用 Hibernate,并且您的服务层捕获HibernateException以对其做出反应。如果您更改为 JPA,您的 DAO 接口不应更改,并且服务层仍将使用捕获的块进行编译HibernateException,但您永远不会进入这些块,因为您的 DAO 现在正在抛出 JPA PersistenceException。通过@Repository在您的 DAO 上使用,与底层技术相关的异常被转换为 Spring DataAccessException;您的服务层会捕获这些异常,如果您决定更改持久性技术,DataAccessExceptions由于 spring 已翻译本机异常,仍将抛出相同的 Spring 。

Note however that this has limited usage for the following reasons:

但是请注意,由于以下原因,这限制了使用:

  1. Your should usually not catch persistence exceptions, as the provider may have rolled back the transaction (depending on the exact exception subtype), and thus you should not continue the execution with an alternative path.
  2. The hierarchy of exceptions is usually richer in your provider than what Spring provides, and there's no definitive mapping from one provider to the other. Relying on this is hazardous. This is however a good idea to annotate your DAOs with @Repository, as the beans will be automatically added by the scan procedure. Further, Spring may add other useful features to the annotation.
  1. 您通常不应捕获持久性异常,因为提供程序可能已回滚事务(取决于确切的异常子类型),因此您不应使用替代路径继续执行。
  2. 异常的层次结构通常在您的提供者中比 Spring 提供的更丰富,并且没有从一个提供者到另一个提供者的明确映射。依赖这个是危险的。然而,使用 注释您的 DAO 是个好主意@Repository,因为扫描过程会自动添加 bean。此外,Spring 可能会向注解添加其他有用的功能。

Spring-JDBC

Spring-JDBC

Spring-JDBC provides the JdbcTemplate class, that removes plumbing code and helps you concentrate on the SQL query and parameters. You just need to configure it with a DataSource, and you can then write code like this:

Spring-JDBC 提供了 JdbcTemplate 类,它删除了管道代码并帮助您专注于 SQL 查询和参数。你只需要用一个 配置它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 also provides a JdbcDaoSupport, that you can extend to develop your DAO. It basically defines 2 properties: a DataSource and a JdbcTemplate that both can be used to implement the DAO methods. It also provides an exceptions translator from SQL exceptions to spring DataAccessExceptions.

Spring-JDBC 还提供了一个 JdbcDaoSupport,你可以扩展它来开发你的 DAO。它基本上定义了 2 个属性:一个 DataSource 和一个 JdbcTemplate,它们都可用于实现 DAO 方法。它还提供了从 SQL 异常到 Spring DataAccessExceptions 的异常翻译器。

If you plan to use plain jdbc, this is the module you will need to use.

如果您打算使用普通的 jdbc,这就是您需要使用的模块。

Spring-ORM

弹簧ORM

Spring-ORM is an umbrella module that covers many persistence technologies, namely JPA, JDO, Hibernate and iBatis. For each of these technologies, Spring provides integration classes so that each technology can be used following Spring principles of configuration, and smoothly integrates with Spring transaction management.

Spring-ORM 是一个伞形模块,涵盖了很多持久化技术,即 JPA、JDO、Hibernate 和 iBatis。对于这些技术中的每一种,Spring 都提供了集成类,使每种技术都可以按照 Spring 的配置原则使用,并与 Spring 事务管理顺利集成。

For each technology, the configuration basically consists in injecting a DataSourcebean into some kind of SessionFactoryor EntityManagerFactoryetc. bean. For pure JDBC, there's no need for such integration classes (apart from JdbcTemplate), as JDBC only relies on a DataSource.

对于每种技术,配置基本上包括将一个DataSourcebean 注入到某种SessionFactoryEntityManagerFactoryetc. bean 中。对于纯 JDBC,不需要此类集成类(JdbcTemplate 除外),因为 JDBC 仅依赖于 DataSource。

If you plan to use an ORM like JPA or Hibernate, you will not need spring-jdbc, but only this module.

如果你打算使用像 JPA 或 Hibernate 这样的 ORM,你将不需要 spring-jdbc,而只需要这个模块。

Spring-Data

Spring-Data

Spring-Data is an umbrella project that provides a common API to define how to access data (DAO + annotations) in a more generic way, covering both SQL and NOSQL data sources.

Spring-Data 是一个伞形项目,它提供了一个通用 API 来定义如何以更通用的方式访问数据(DAO + 注释),涵盖 SQL 和 NOSQL 数据源。

The initial idea is to provide a technology so that the developer writes the interface for a DAO (finder methods) and the entity classes in a technology-agnostic way and, based on configuration only (annotations on DAOs & entities + spring configuration, be it xml- or java-based), decides the implementation technology, be it JPA (SQL) or redis, hadoop, etc. (NOSQL).

最初的想法是提供一种技术,以便开发人员以与技术无关的方式编写 DAO(finder 方法)和实体类的接口,并且仅基于配置(DAO 和实体上的注释 + spring 配置,无论是xml-or java-based),决定了实现技术,无论是JPA(SQL)还是redis、hadoop等(NOSQL)。

If you follow the naming conventions defined by spring for the finder method names, you don't even need to provide the query strings corresponding to finder methods for the most simple cases. For other situations, you have to provide the query string inside annotations on the finder methods.

如果您遵循 spring 为 finder 方法名称定义的命名约定,则对于最简单的情况,您甚至不需要提供与 finder 方法对应的查询字符串。对于其他情况,您必须在 finder 方法的注释内提供查询字符串。

When the application context is loaded, spring provides proxies for the DAO interfaces, that contain all the boilerplate code related to the data access technology, and invokes the configured queries.

加载应用程序上下文时,spring 为 DAO 接口提供代理,其中包含与数据访问技术相关的所有样板代码,并调用配置的查询。

Spring-Data concentrates on non-SQL technologies, but still provides a module for JPA (the only SQL technology).

Spring-Data 专注于非 SQL 技术,但仍然为 JPA(唯一的 SQL 技术)提供了一个模块。

What's next

下一步是什么

Knowing all this, you have now to decide what to pick. The good news here is that you don't need to make a definitive final choice for the technology. This is actually where Spring power resides : as a developer, you concentrate on the business when you write code, and if you do it well, changing the underlying technology is an implementation or configuration detail.

了解所有这些后,您现在必须决定选择什么。好消息是,您无需为该技术做出明确的最终选择。这其实就是 Spring 的力量所在:作为开发者,你在写代码的时候专注于业务,如果你做得好,改变底层技术是一个实现或配置细节。

  1. Define a data model with POJO classes for the entities, and get/set methods to represent the entity attributes and the relationships to other entities. You will certainly need to annotate the entity classes and fields based on the technology, but for now, POJOs are enough to start with. Just concentrate on the business requirements for now.
  2. Define interfaces for your DAOs. 1 DAO covers exactly 1 entity, but you will certainly not need a DAO for each of them, as you should be able to load additional entities by navigating the relationships. Define the finder methods following strict naming conventions.
  3. Based on this, someone else can start working on the services layer, with mocks for your DAOs.
  4. You learn the different persistence technologies (sql, no-sql) to find the best fit for your needs, and choose one of them. Based on this, you annotate the entities and implement the DAOs (or let spring implement them for you if you choose to use spring-data).
  5. If the business requirements evolve and your data access technology is not sufficient to support it (say, you started with JDBC and a few entities, but now need a richer data model and JPA is a better choice), you will have to change the implementation of your DAOs, add a few annotations on your entities and change the spring configuration (add an EntityManagerFactory definition). The rest of your business code should not see other impacts from your change.
  1. 使用实体的 POJO 类定义数据模型,并使用 get/set 方法来表示实体属性和与其他实体的关系。您当然需要根据技术对实体类和字段进行注释,但就目前而言,POJO 已足够开始。现在只需专注于业务需求。
  2. 为您的 DAO 定义接口。1 个 DAO 正好涵盖 1 个实体,但您肯定不需要为每个实体都使用 DAO,因为您应该能够通过导航关系加载其他实体。按照严格的命名约定定义 finder 方法。
  3. 基于此,其他人可以开始在服务层上工作,并为您的 DAO 进行模拟。
  4. 您将学习不同的持久性技术(sql、no-sql)以找到最适合您需求的技术,并从中选择一种。基于此,您可以注释实体并实现 DAO(或者,如果您选择使用 spring-data,则让 spring 为您实现它们)。
  5. 如果业务需求不断发展,而您的数据访问技术不足以支持它(例如,您从 JDBC 和一些实体开始,但现在需要更丰富的数据模型,而 JPA 是更好的选择),您将不得不更改实现在您的 DAO 中,在您的实体上添加一些注释并更改 spring 配置(添加 EntityManagerFactory 定义)。您的业​​务代码的其余部分不应受到更改的其他影响。

Note : Transaction Management

注意:交易管理

Spring provides an API for transaction management. If you plan to use spring for the data access, you should also use spring for transaction management, as they integrate together really well. For each data access technology supported by spring, there is a matching transaction manager for local transactions, or you can choose JTA if you need distributed transactions. All of them implement the same API, so that (once again) the technology choice is just a matter a configuration that can be changed without further impact on the business code.

Spring 提供了一个用于事务管理的 API。如果您打算使用 spring 进行数据访问,那么您还应该使用 spring 进行事务管理,因为它们可以很好地集成在一起。spring支持的每一种数据访问技术,都有匹配的本地事务的事务管理器,如果需要分布式事务也可以选择JTA。它们都实现了相同的 API,因此(再次)技术选择只是一个可以更改的配置,而不会进一步影响业​​务代码。

Note : Spring documentation

注意:Spring 文档

The links to Spring documentation that you mentioned are rather old. Here is the documentation of the latest release (4.1.6, covering all topics) :

您提到的 Spring 文档的链接相当陈旧。这是最新版本(4.1.6,涵盖所有主题)的文档:

Spring-data is not part of the Spring framework. There is a common module that you should first read to get used to the principles. Documentation can be found here:

Spring-data 不是 Spring 框架的一部分。有一个通用模块,您应该首先阅读以习惯这些原则。文档可以在这里找到:

回答by Premraj

Spring DAO(Data Access Object): is an object that provides an abstract interface to JDBC implementation frameworks i.e. Spring DAO is generalizedconcept to access JDBC and Hibernate, MyBatis, JPA, JDO using it's individual Support classes. And it provides generalizedexception hierarchy by defining @Repositoryannotation. This annotation defines to Spring container for SQL exception translationfrom SQLExceptionto Spring's data access strategy-agnostic DataAccessExceptionhierarchy.

春天DAOdATA一个CCESS Øbject):是提供的抽象接口JDBC执行框架的目标,即春季DAO是 广义使用它的个性化支持类概念访问JDBC和Hibernate,MyBatis的,JPA,JDO。并且它通过定义注解提供了通用的异常层次结构@Repository。这个注解定义为Spring容器SQL异常转换SQLExceptionSpring的数据访问策略无关的 DataAccessException层次结构。

i.e. platform specific exceptions are catches and then re-throws as one of Spring's unchecked data access exceptions.

即平台特定的异常被捕获,然后作为 Spring 的未经检查的数据访问异常之一重新抛出。



Spring JDBC: For plain JDBC we use this module, which is only depends on DataSourceand Template classes like JdbcTemplate, NamedParameterJdbcTemplate(wraps JdbcTemplate) and SimpleJdbcTemplatefor reducing cross cutting concerns.

Spring JDBC:对于普通的 JDBC,我们使用这个模块,它只依赖于DataSource模板类,如JdbcTemplate, NamedParameterJdbcTemplate(wraps 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);  
}  

}  

and in Spring XML:

在 Spring XML 中:

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

Spring JDBC also provides JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport, which are support(i.e. convenient) way to extend and develop our own DAOabstract interface as follows:

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

and in spring XML:

并在春季 XML 中:

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


Spring ORM:For ORM tools support such as Hibernate, JPA, MyBatis...easily integrates Spring by injecting DataSourcealong with following classes and respective DaoSupportclasses.

Spring ORM:对于 Hibernate、JPA、MyBatis 等 ORM 工具的支持……通过注入DataSource以下类和各自的DaoSupport类,轻松集成 Spring 。

  • SessionFactoryfor Hibernate
  • EntityManagerFactoryfor JPA,
  • SqlSessionFactoryfor MyBatis
  • SessionFactory用于休眠
  • EntityManagerFactory对于 JPA,
  • SqlSessionFactory用于 MyBatis

回答by Paulo Merson

The spring-dao lib stopped in version 2.0.8 (January 2008). The classes in spring-dao were copied to spring-tx. So, if you need a class that you find in spring-dao, add the dependency to spring-txinstead. (Source.)

spring-dao 库在 2.0.8 版(2008 年 1 月)中停止。spring-dao 中的类被复制到 spring-tx。因此,如果您需要在 spring-dao 中找到的类,请将依赖项添加到spring-tx 中。(来源。)

回答by Brandon Osorio

As an additional info. I suggest you use Spring Data JPA. Using anotations such as: @Repository, @Service. I show you an example:

作为附加信息。我建议您使用 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);

}

Where CustomerEntitlementsProjection is Spring projection, linked with you entity or DTO pojo;

其中 CustomerEntitlementsProjection 是 Spring 投影,与您的实体或 DTO pojo 相关联;

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

  String getContractNumber();

  String getExecutiveNumber();

回答by mike_m

You create interface like SomeObjectDaoand then create different implementations of this interface like JdbcSomeObjectDao, HibernateSomeObjectDao. Then in your SomeObjectServiceclass you will operate on the SomeObjectDaointerface, and inject there one of the concrete implementations. So each implementation of SomeObjectDaowill hide the details, whether you use JDBC, or ORM etc.

您创建类似接口SomeObjectDao,然后创建该接口的不同实现,例如JdbcSomeObjectDao, HibernateSomeObjectDao。然后在您的SomeObjectService课程中,您将对SomeObjectDao接口进行操作,并在其中注入具体实现之一。所以每个实现SomeObjectDao都会隐藏细节,无论你使用JDBC,还是ORM等。

Usually JDBC, and different implementations of ORM throws different kind of exceptions. Spring's DAO supportcan map those different, technology specific exceptions to common Spring DAO exceptions. So you are decoupled more from the actual implementation. Also Spring's DAO supportoffers set of abstract *DataSupportclasses which even more help in DAO development. So beside implementing your SomeObjectDaointerface, you can extend one of Spring's *DataSupportclass.

通常 JDBC 和 ORM 的不同实现会抛出不同类型的异常。Spring 的DAO 支持可以将这些不同的、特定于技术的异常映射到常见的 Spring DAO 异常。因此,您与实际实现的分离程度更高。Spring 的DAO 支持还提供了一组抽象*DataSupport类,这对 DAO 开发更有帮助。因此,除了实现您的SomeObjectDao接口之外,您还可以扩展 Spring 的*DataSupport类之一。