这里是每个提到的技术的介绍。
Spring-DAO
Spring-DAO 不是严格意义上的 spring 模块,而是应该要求你编写 DAO 并写好它们的约定。因此,它既不提供接口也不提供实现或模板来访问您的数据。编写 DAO 时,应使用 @Repository 注释它们,以便与底层技术(JDBC、Hibernate、JPA 等)相关的异常始终转换为正确的 DataAccessException 子类。
例如,假设您现在正在使用 Hibernate,并且您的服务层捕获 HibernateException 以便对其做出反应。如果您更改为 JPA,您的 DAO 接口不应更改,并且服务层仍将使用捕获 HibernateException 的块进行编译,但您将永远不会进入这些块,因为您的 DAO 现在正在抛出 JPA PersistenceException。通过在你的 DAO 上使用 @Repository,与底层技术相关的异常被转换为 Spring DataAccessException;您的服务层会捕获这些异常,如果您决定更改持久性技术,仍然会抛出相同的 Spring DataAccessExceptions,因为 spring 已经翻译了本机异常。
但请注意,由于以下原因,它的使用受到限制:
- 您通常不应捕获持久性异常,因为提供程序可能已回滚事务(取决于确切的异常子类型),因此您不应使用替代路径继续执行。
- 提供程序中的异常层次结构通常比 Spring 提供的更丰富,并且从一个提供程序到另一个提供程序没有明确的映射。依赖它是危险的。
然而,使用
@Repository 注释 DAO 是一个好主意,因为扫描过程会自动添加 bean。此外,Spring 可能会在注释中添加其他有用的功能。
Spring-JDBC
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 还提供了一个 JdbcDaoSupport,你可以扩展它来开发你的 DAO。它基本上定义了 2 个属性:一个 DataSource 和一个 JdbcTemplate,它们都可用于实现 DAO 方法。它还提供了一个从 SQL 异常到 Spring DataAccessExceptions 的异常转换器。
如果您打算使用纯 jdbc,这是您需要使用的模块。
Spring-ORM
Spring-ORM 是一个涵盖许多持久性技术的伞形模块,即 JPA、JDO、Hibernate 和 iBatis。对于每一种技术,Spring 都提供了集成类,使每一种技术都可以按照 Spring 的配置原则使用,并与 Spring 事务管理顺利集成。
对于每种技术,配置基本上包括将DataSource bean 注入某种SessionFactory 或EntityManagerFactory 等bean。对于纯 JDBC,不需要这样的集成类(除了 JdbcTemplate),因为 JDBC 只依赖于 DataSource。
如果你打算使用 JPA 或 Hibernate 之类的 ORM,则不需要 spring-jdbc,而只需要这个模块。
Spring-Data
Spring-Data 是一个伞形项目,它提供了一个通用 API 来定义如何以更通用的方式访问数据(DAO + 注释),涵盖 SQL 和 NOSQL 数据源。
最初的想法是提供一种技术,以便开发人员以与技术无关的方式为 DAO(查找器方法)和实体类编写接口,并且仅基于配置(DAO 和实体的注释 + spring 配置,无论是基于xml还是基于java),决定实现技术,无论是JPA(SQL)还是redis,hadoop等(NOSQL)。
如果你遵循 spring 为 finder 方法名称定义的命名约定,那么对于最简单的情况,你甚至不需要提供对应于 finder 方法的查询字符串。对于其他情况,您必须在 finder 方法的注释中提供查询字符串。
当应用程序上下文被加载时,spring 为 DAO 接口提供代理,其中包含与数据访问技术相关的所有样板代码,并调用配置的查询。
Spring-Data 专注于非 SQL 技术,但仍为 JPA(唯一的 SQL 技术)提供模块。
接下来是什么
了解了这一切之后,您现在必须决定选择什么。这里的好消息是,您无需为该技术做出明确的最终选择。这实际上是 Spring 的力量所在:作为开发人员,您在编写代码时专注于业务,如果您做得好,更改底层技术就是一个实现或配置细节。
- 为实体定义一个带有 POJO 类的数据模型,并使用 get/set 方法来表示实体属性以及与其他实体的关系。您当然需要根据技术对实体类和字段进行注释,但现在,POJO 已经足够开始了。现在只关注业务需求。
- 为您的 DAO 定义接口。 1 个 DAO 恰好涵盖 1 个实体,但您当然不需要为每个实体创建一个 DAO,因为您应该能够通过导航关系来加载其他实体。按照严格的命名约定定义查找器方法。
- 基于此,其他人可以开始在服务层上工作,并为您的 DAO 模拟。
- 您学习不同的持久性技术(sql、no-sql)以找到最适合您需求的技术,然后选择其中一种。在此基础上,您注释实体并实现 DAO(如果您选择使用 spring-data,则让 spring 为您实现它们)。
- 如果业务需求不断发展,而您的数据访问技术不足以支持它(例如,您开始使用 JDBC 和一些实体,但现在需要更丰富的数据模型,而 JPA 是更好的选择),您将不得不更改 DAO 的实现,在实体上添加一些注释并更改 spring 配置(添加 EntityManagerFactory 定义)。您的业务代码的其余部分不应受到您的更改的其他影响。
注意:事务管理
Spring 提供了一个用于事务管理的 API。如果您打算使用 spring 进行数据访问,您还应该使用 spring 进行事务管理,因为它们很好地集成在一起。对于spring支持的每一种数据访问技术,都有一个匹配的本地事务的事务管理器,或者如果需要分布式事务可以选择JTA。它们都实现了相同的 API,因此(再次)技术选择只是一个可以更改而不会对业务代码产生进一步影响的配置。
注意:Spring 文档
您提到的 Spring 文档的链接相当陈旧。这是最新版本(4.1.6,涵盖所有主题)的文档:
Spring-data 不是 Spring 框架的一部分。您应该首先阅读一个通用模块以习惯这些原则。文档可以在这里找到: