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 层次结构的一个子集)。
用于配置 DAO 或 Repository 类的注解
Annotations Used to Configure DAO or Repository Classes
保证你的数据访问对象(DAO)或存储库提供异常翻译的最好方法是使用 @Repository
注解。这个注解还可以让组件扫描支持找到并配置你的 DAO 和存储库,而不需要为它们提供 XML 配置条目。下面的例子展示了如何使用 @Repository
注解:
@Repository
public class SomeMovieFinder implements MovieFinder {
// ...
}
任何 DAO 或资源库的实现都需要访问一个持久化资源,这取决于所使用的持久化技术。例如,基于 JDBC 的存储库需要访问 JDBC DataSource,而基于 JPA 的存储库需要访问 EntityManager。最简单的方法是通过使用 @Autowired
, @Inject
, @Resource
或 @PersistenceContext
注解之一来注入这种资源依赖关系。下面的例子适用于 JPA 资源库:
@Repository
public class JpaMovieFinder implements MovieFinder {
@PersistenceContext
private EntityManager entityManager;
// ...
}
如果你使用经典的 Hibernate APIs,你可以注入 SessionFactory,如下例所示:
@Repository
public class HibernateMovieFinder implements MovieFinder {
private SessionFactory sessionFactory;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// ...
}
我们在这里展示的最后一个例子是用于典型的 JDBC 支持。你可以将 DataSource 注入到初始化方法或构造函数中,在那里你将通过使用这个 DataSource 创建 JdbcTemplate 和其他数据访问支持类(如 SimpleJdbcCall 和其他)。下面的例子是自动连接一个 DataSource:
@Repository
public class JdbcMovieFinder implements MovieFinder {
private JdbcTemplate jdbcTemplate;
@Autowired
public void init(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// ...
}
:::info 关于如何配置应用程序上下文以利用这些注解的细节,请参见每种持久化技术的具体报道。 :::