DAO 支持
Spring中的数据访问对象(DAO)支持旨在让人们能够以一种一致的方式轻松地使用数据访问技术(如JDBC、Hibernate或JPA)。这使你能够相对容易地在上述持久化技术之间切换,同时也让你在编码时无需担心捕获每种技术特有的异常。
一致的异常层次结构
Spring 提供了一个便捷的转换机制,可以将特定于技术的异常(如 SQLException)转换为它自己的异常类层次结构中的异常,该层次结构的根异常是 DataAccessException。这些异常会封装原始异常,因此你永远不会失去关于可能出错情况的任何信息。
除了JDBC异常之外,Spring还可以封装JPA和Hibernate特有的异常,将它们转换为一系列专注的运行时异常。这样你就可以只在适当的层面上处理大多数不可恢复的持久化异常,而无需在DAO中编写繁琐的捕获和抛出异常的代码以及异常声明。(不过,你仍然可以在需要的地方捕获和处理异常。)如上所述,JDBC异常(包括特定于数据库的方言异常)也会被转换为相同的异常层次结构,这意味着你可以在一个统一的编程模型内使用JDBC进行某些操作。
上述讨论同样适用于Spring对各种ORM框架的支持所涉及的各类模板类。如果您使用基于拦截器的类,那么应用程序本身就必须负责处理HibernateExceptions和PersistenceExceptions,最好是通过分别调用SessionFactoryUtils的convertHibernateAccessException(..)或convertJpaAccessException(..)方法来处理这些异常。这些方法会将异常转换为与org.springframework.dao异常层次结构中兼容的异常类型。由于PersistenceExceptions是未检查型异常(unchecked exceptions),它们也可能被抛出(不过这样一来,在异常处理方面就牺牲了通用DAO抽象的优越性)。
下图展示了Spring提供的异常层次结构。(请注意,图中显示的类层次结构仅代表整个DataAccessException层次结构的一个子集。)

用于配置DAO或Repository类的注解
要确保你的数据访问对象(DAO)或存储库能够提供异常转换,最好的方法是使用@Repository注解。这个注解还可以让组件扫描支持找到并配置你的DAO和存储库,而无需为它们提供XML配置项。以下示例展示了如何使用@Repository注解:
- Java
- Kotlin
@Repository 1
public class SomeMovieFinder implements MovieFinder {
// ...
}
@Repository注解。
@Repository 1
class SomeMovieFinder : MovieFinder {
// ...
}
@Repository注解。
任何DAO或仓库实现都需要访问持久化资源,这取决于所使用的持久化技术。例如,基于JDBC的仓库需要访问JDBC的DataSource,而基于JPA的仓库需要访问EntityManager。实现这一点的最简单方法是使用@Autowired、@Inject、@Resource或@PersistenceContext等注解来注入这些资源依赖。以下示例适用于JPA仓库:
- Java
- Kotlin
@Repository
public class JpaMovieFinder implements MovieFinder {
@PersistenceContext
private EntityManager entityManager;
// ...
}
@Repository
class JpaMovieFinder : MovieFinder {
@PersistenceContext
private lateinit var entityManager: EntityManager
// ...
}
如果你使用经典的Hibernate API,你可以注入SessionFactory,如下例所示:
- Java
- Kotlin
@Repository
public class HibernateMovieFinder implements MovieFinder {
private SessionFactory sessionFactory;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// ...
}
@Repository
class HibernateMovieFinder(private val sessionFactory: SessionFactory) : MovieFinder {
// ...
}
我们在这里展示的最后一个示例是关于典型的JDBC支持的。你可以将DataSource注入到初始化方法或构造函数中,在那里你可以使用这个DataSource来创建JdbcTemplate和其他数据访问支持类(如SimpleJdbcCall等)。以下示例实现了DataSource的自动注入:
- Java
- Kotlin
@Repository
public class JdbcMovieFinder implements MovieFinder {
private JdbcTemplate jdbcTemplate;
@Autowired
public void init(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// ...
}
@Repository
class JdbcMovieFinder(dataSource: DataSource) : MovieFinder {
private val jdbcTemplate = JdbcTemplate(dataSource)
// ...
}
有关如何配置应用程序上下文以利用这些注解的详细信息,请参阅每种持久化技术的具体说明。