# 2.DAO支持

Spring对数据访问对象（DAO）的支持旨在使以一致的方式轻松使用数据访问技术（例如JDBC，Hibernate或JPA）。这使你可以轻松地在上述持久性技术之间进行切换，还使你无需担心捕获每种技术特有的异常即可进行编码。

## 2.1 一致的异常层次结构

Spring提供了从特定于技术的异常（例如SQLException）到其自己的异常类层次结构的便捷转换，该异常类层次结构以DataAccessException作为根异常。这些异常包装了原始异常，因此你永远不会丢失任何可能出错的信息。

除了JDBC异常，Spring还可以包装JPA和Hibernate特定的异常，将它们转换为一组集中的运行时异常。这样，你就可以仅在适当的层中处理大多数不可恢复的持久性异常，而无需在DAO中使用烦人的样板捕获和抛出块以及异常声明。 （尽管你仍然可以在任何需要的地方捕获和处理异常。）如上所述，JDBC异常（包括特定于数据库的方言）也被转换为相同的层次结构，这意味着你可以在一致的编程模型中对JDBC执行某些操作。 。

在Spring对各种ORM框架的支持中，上述讨论对于各种模板类均适用。如果使用基于拦截器的类，则应用程序必须关心如何处理HibernateExceptions和PersistenceExceptions本身，最好分别委派给SessionFactoryUtils的convertHibernateAccessException（..）或convertJpaAccessException（）方法。这些方法将异常转换为与org.springframework.dao异常层次结构中的异常兼容的异常。由于未选中PersistenceException，因此也可能引发它们（不过，在异常方面牺牲了通用DAO抽象）。

下图显示了Spring提供的异常层次结构。 （请注意，图像中详细描述的类层次结构仅显示整个DataAccessException层次结构的子集。）

![](https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/images/DataAccessException.png)

## 2.2 用于配置DAO或存储库类的注解

保证数据访问对象（DAO）或存储库提供异常转换的最佳方法是使用@Repository批注。 此批注还允许组件扫描支持查找和配置DAO和存储库，而无需为它们提供XML配置条目。 以下示例显示了如何使用@Repository批注：

```java
@Repository 
public class SomeMovieFinder implements MovieFinder {
    // ...
}
```

任何DAO或存储库实现都需要访问持久性资源，具体取决于所使用的持久性技术。 例如，基于JDBC的存储库需要访问JDBC DataSource，而基于JPA的存储库需要访问EntityManager。 完成此操作的最简单方法是使用@Autowired，@ Inject，@ Resource或@PersistenceContext注解之一注入此资源依赖项。 以下示例适用于JPA存储库：

```java
@Repository
public class JpaMovieFinder implements MovieFinder {

    @PersistenceContext
    private EntityManager entityManager;

    // ...

}
```

如果你使用经典的Hibernate API，则可以注入SessionFactory，如以下示例所示：

```java
@Repository
public class HibernateMovieFinder implements MovieFinder {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    // ...

}
```

我们在这里展示的最后一个例子是典型的JDBC支持。 你可以将DataSource注入到初始化方法中，你可以使用此DataSource在其中创建JdbcTemplate和其他数据访问支持类（如SimpleJdbcCall等）。 以下示例自动装配DataSource：

```java
@Repository
public class JdbcMovieFinder implements MovieFinder {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void init(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    // ...

}
```
