Appearance
Spring 数据访问:DAO 支持
Tip:基于 Spring Core 5.3.30 版本。
Spring 中的数据访问对象(DAO,Data Access Object)支持旨在使得使用数据访问技术(如 JDBC、Hibernate 或 JPA)变得简单且一致。这让你可以在上述的持久化技术之间轻松切换,同时也让你在编码时无需担心捕获每种技术特有的异常。
1. 一致的异常层次结构
Spring 提供了一种方便的从技术特定异常(如 SQLException)到其自身异常类层次结构的转换,其中 DataAccessException 是根异常。这些异常包装了原始异常,因此你永远不会丢失任何可能出错的信息。
除了 JDBC 异常,Spring 也可以包装 JPA 和 Hibernate 特定的异常,将它们转换为一组专注的运行时异常。这让你可以在适当的层次中处理大多数不可恢复的持久性异常,而无需在你的 DAO 中有烦人的样板 catch-and-throw 块和异常声明。(你仍然可以在需要的任何地方捕获和处理异常。)如上所述,JDBC 异常(包括数据库特定的方言)也被转换为相同的层次结构,这意味着你可以在一个一致的编程模型中执行一些 JDBC 操作。
前面的讨论对于 Spring 对各种 ORM 框架的支持中的各种模板类都是适用的。如果你使用基于拦截器的类,应用程序必须自己处理 HibernateExceptions 和 PersistenceExceptions,最好是委托给 SessionFactoryUtils 的 convertHibernateAccessException(..) 或 convertJpaAccessException(..) 方法。这些方法将异常转换为与 org.springframework.dao 异常层次结构中的异常兼容的异常。由于 PersistenceExceptions 是未经检查的,它们也可以被抛出(尽管这样做会牺牲异常方面的通用 DAO 抽象)。
下面的图片显示了 Spring 提供的异常层次结构。(请注意,图片中详细描述的类层次结构只显示了整个 DataAccessException 层次结构的一部分。)

DataAccessException 的部分层次结构2. 用于配置 DAO 或仓库类的注解
确保你的数据访问对象(DAOs,Data Access Objects)或者仓库能提供异常转换的最佳方式是使用 @Repository 注解。这个注解也让组件扫描支持能找到并配置你的 DAOs 和仓库,而无需为它们提供 XML 配置条目。下面的示例展示了如何使用 @Repository 注解:
Java
@Repository
public class SomeMovieFinder implements MovieFinder {
// ...
}1
2
3
4
2
3
4
任何 DAO 或仓库实现都需要访问持久化资源,这取决于所使用的持久化技术。例如,基于 JDBC 的仓库需要访问 JDBC DataSource,而基于 JPA 的仓库需要访问 EntityManager。实现这一点的最简单方法是通过使用 @Autowired、@Inject、@Resource 或 @PersistenceContext 注解来注入这种资源依赖。以下示例适用于 JPA 仓库:
Java
@Repository
public class JpaMovieFinder implements MovieFinder {
@PersistenceContext
private EntityManager entityManager;
// ...
}1
2
3
4
5
6
7
2
3
4
5
6
7
如果你使用经典的 Hibernate API,你可以注入 SessionFactory,如下例所示:
Java
@Repository
public class HibernateMovieFinder implements MovieFinder {
private SessionFactory sessionFactory;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// ...
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
我们在这里展示的最后一个示例是针对典型的 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);
}
// ...
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Note:你可以参考每种持久化技术的具体内容,了解如何配置应用上下文以充分利用这些注解。