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
是未检查的,它们也可以被抛出(尽管牺牲了异常方面的通用 DAO 抽象)。
下图显示了 Spring 提供的异常层次结构。(请注意,图中详细说明的类层次结构仅显示了整个 DataAccessException
层次结构的一个子集。)

用于配置 DAO 或 Repository 类的注解
确保您的数据访问对象 (DAO) 或存储库提供异常转换的最佳方法是使用 @Repository
注解。此注解还允许组件扫描支持查找和配置您的 DAO 和存储库,而无需为它们提供 XML 配置条目。以下示例显示了如何使用 @Repository
注解:
- Java
-
@Repository [id="CO1-1"][id="CO1-1"][id="CO1-1"](1) public class SomeMovieFinder implements MovieFinder { // ... }
<1> `@Repository` 注解。
- Kotlin
-
@Repository [id="CO2-1"][id="CO1-2"][id="CO2-1"](1) class SomeMovieFinder : MovieFinder { // ... }
<1> `@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)
// ...
}
有关如何配置应用程序上下文以利用这些注解的详细信息,请参阅每种持久化技术的具体介绍。 |