DAO Support

Spring 中的数据访问对象(Data Access Object 简称 DAO)支持旨在使数据访问技术(如 JDBC、Hibernate 或 JPA)以一致的方式轻松工作。这可以让你在上述持久化技术之间轻松切换,也可以让你在编码时不必担心捕捉每种技术特有的异常。

一致的异常层次结构

Consistent Exception Hierarchy

Spring 提供了一个方便的翻译,从特定技术的异常,如 SQLException 到它自己的异常类层次结构,其中 DataAccessException 是根异常。这些异常包裹着原始的异常,这样就不会有任何风险,你可能会失去任何关于可能出错的信息。

除了 JDBC 异常外,Spring 还可以包装 JPA 和 Hibernate 特定的异常,将它们转换为一组集中的运行时异常。这让你只需在适当的层中处理大多数不可恢复的持久性异常,而无需在 DAO 中使用恼人的模板式捕获和抛出块(catch-and-throw)以及异常声明。(如上所述,JDBC 的异常(包括数据库特定的方言)也被转换为相同的层次结构,这意味着你可以在一个一致的编程模型中用 JDBC 进行一些操作。

前面的讨论对 Spring 支持各种 ORM 框架的各种模板类(template)都是适用的。如果你使用基于拦截器的类,应用程序必须关心处理HibernateExceptions 和 PersistenceExceptions 本身,最好是分别委托给 SessionFactoryUtils 的 convertHibernateAccessException(.)convertJpaAccessException(.)方法。这些方法将异常转换为与org.springframework.dao异常层次结构中的异常兼容的异常。由于 PersistenceExceptions 没有被选中,它们也可以被抛出(虽然在异常方面牺牲了通用的 DAO 抽象性)。

下面的图片显示了 Spring 提供的异常层次结构。(请注意,图片中详述的类的层次结构只显示了整个 DataAccessException 层次结构的一个子集)。
image.png

用于配置 DAO 或 Repository 类的注解

Annotations Used to Configure DAO or Repository Classes

保证你的数据访问对象(DAO)或存储库提供异常翻译的最好方法是使用 @Repository注解。这个注解还可以让组件扫描支持找到并配置你的 DAO 和存储库,而不需要为它们提供 XML 配置条目。下面的例子展示了如何使用 @Repository注解:

  1. @Repository
  2. public class SomeMovieFinder implements MovieFinder {
  3. // ...
  4. }

任何 DAO 或资源库的实现都需要访问一个持久化资源,这取决于所使用的持久化技术。例如,基于 JDBC 的存储库需要访问 JDBC DataSource,而基于 JPA 的存储库需要访问 EntityManager。最简单的方法是通过使用 @Autowired, @Inject, @Resource@PersistenceContext 注解之一来注入这种资源依赖关系。下面的例子适用于 JPA 资源库:

  1. @Repository
  2. public class JpaMovieFinder implements MovieFinder {
  3. @PersistenceContext
  4. private EntityManager entityManager;
  5. // ...
  6. }

如果你使用经典的 Hibernate APIs,你可以注入 SessionFactory,如下例所示:

  1. @Repository
  2. public class HibernateMovieFinder implements MovieFinder {
  3. private SessionFactory sessionFactory;
  4. @Autowired
  5. public void setSessionFactory(SessionFactory sessionFactory) {
  6. this.sessionFactory = sessionFactory;
  7. }
  8. // ...
  9. }

我们在这里展示的最后一个例子是用于典型的 JDBC 支持。你可以将 DataSource 注入到初始化方法或构造函数中,在那里你将通过使用这个 DataSource 创建 JdbcTemplate 和其他数据访问支持类(如 SimpleJdbcCall 和其他)。下面的例子是自动连接一个 DataSource:

  1. @Repository
  2. public class JdbcMovieFinder implements MovieFinder {
  3. private JdbcTemplate jdbcTemplate;
  4. @Autowired
  5. public void init(DataSource dataSource) {
  6. this.jdbcTemplate = new JdbcTemplate(dataSource);
  7. }
  8. // ...
  9. }

:::info 关于如何配置应用程序上下文以利用这些注解的细节,请参见每种持久化技术的具体报道。 :::