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

用于配置 DAO 或 Repository 类的注解
确保你的 Data Access Objects (DAO) 或 repository 提供异常转换的最佳方法是使用 `@Repository` 注解。这个注解还允许组件扫描支持找到并配置你的 DAO 和 repository,而无需为其提供 XML 配置条目。以下示例展示了如何使用 `@Repository` 注解
-
Java
-
Kotlin
@Repository (1)
public class SomeMovieFinder implements MovieFinder {
// ...
}
1 | `@Repository` 注解。 |
@Repository (1)
class SomeMovieFinder : MovieFinder {
// ...
}
1 | `@Repository` 注解。 |
任何 DAO 或 repository 实现都需要访问持久化资源,这取决于所使用的持久化技术。例如,基于 JDBC 的 repository 需要访问 JDBC DataSource
,而基于 JPA 的 repository 需要访问 EntityManager
。最简单的方法是使用 `@Autowired`、`@Inject`、`@Resource` 或 `@PersistenceContext` 注解中的一个来注入这个资源依赖。以下示例适用于 JPA repository
-
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)
// ...
}
有关如何配置应用程序上下文以利用这些注解的详细信息,请参阅每种持久化技术的具体介绍。 |