|
对于最新稳定版本,请使用 Spring Framework 7.0.6! |
DAO 支持
Spring 中的数据访问对象(DAO)支持旨在以一致的方式简化与数据访问技术(如 JDBC、Hibernate 或 JPA)的交互。这使得你能够相当轻松地在上述持久化技术之间进行切换,同时也让你无需担心捕获特定于每种技术的异常。
一致的异常层次结构
Spring 提供了一种便捷的机制,可将特定技术的异常(例如 SQLException)转换为其自身的异常类层次结构,该层次结构以 DataAccessException 作为根异常。这些异常会包装原始异常,因此您永远不会丢失任何有关可能出错原因的信息。
除了 JDBC 异常之外,Spring 还可以封装 JPA 和 Hibernate 特有的异常, 将它们转换为一组聚焦的运行时异常。这使你能够在适当的层中处理大多数 不可恢复的持久化异常,而无需在 DAO 中编写烦人的样板式 catch-and-throw 代码块和异常声明。 (当然,你仍然可以在任何需要的地方捕获并处理异常。)如上所述, JDBC 异常(包括数据库特定的方言)也会被转换到相同的异常层次结构中, 这意味着你可以在一致的编程模型中使用 JDBC 执行某些操作。
上述讨论适用于 Spring 对各种 ORM 框架支持中的各类模板类。如果你使用基于拦截器的类,应用程序必须自行处理 HibernateExceptions 和 PersistenceExceptions,最好分别委托给 convertHibernateAccessException(..) 类中的 convertJpaAccessException(..) 或 SessionFactoryUtils 方法。这些方法会将异常转换为与 org.springframework.dao 异常体系结构兼容的异常。由于 PersistenceExceptions 是非受检异常(unchecked),它们也可以直接抛出(尽管这样做会牺牲在异常层面的通用 DAO 抽象)。
下图展示了 Spring 提供的异常层次结构。
(请注意,图中所示的类层次结构仅展示了整个
DataAccessException 层次结构的一个子集。)
用于配置 DAO 或 Repository 类的注解
确保你的数据访问对象(DAO)或仓库提供异常转换的最佳方式是使用 @Repository 注解。该注解还能让组件扫描功能自动发现并配置你的 DAO 和仓库,而无需为它们提供 XML 配置项。以下示例展示了如何使用 @Repository 注解:
-
Java
-
Kotlin
@Repository (1)
public class SomeMovieFinder implements MovieFinder {
// ...
}
| 1 | @Repository注解。 |
@Repository (1)
class SomeMovieFinder : MovieFinder {
// ...
}
| 1 | @Repository注解。 |
任何 DAO 或仓库(repository)实现都需要访问持久化资源,具体取决于所使用的持久化技术。例如,基于 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 注入到初始化方法或构造函数中,在其中使用该 JdbcTemplate 创建 SimpleJdbcCall 和其他数据访问支持类(例如 DataSource 等)。以下示例自动装配了一个 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)
// ...
}
| 见每个持久化技术的具体覆盖范围,以了解如何配置应用上下文以便利用这些注解。 |