DAO Support
Spring 中的数据访问对象 (DAO) 支持旨在使以一致的方式使用数据访问技术(例如 JDBC、Hibernate 或 JPA)变得容易。这使你可以相对轻松地在上述持久性技术之间切换,而且它还能让你在不用担心捕获特定于每种技术异常的情况下编写代码。
The Data Access Object (DAO) support in Spring is aimed at making it easy to work with data access technologies (such as JDBC, Hibernate, or JPA) in a consistent way. This lets you switch between the aforementioned persistence technologies fairly easily, and it also lets you code without worrying about catching exceptions that are specific to each technology.
Consistent Exception Hierarchy
Spring 提供从特定于技术的异常(如 SQLException
)到其自身异常类层次结构的便捷转换,其根异常为 DataAccessException
。这些异常包装了原始异常,因此不存在丢失可能有误信息的不良风险。
Spring provides a convenient translation from technology-specific exceptions, such as
SQLException
to its own exception class hierarchy, which has DataAccessException
as
the root exception. These exceptions wrap the original exception so that there is never
any risk that you might lose any information about what might have gone wrong.
除 JDBC 异常外,Spring 还可以包装 JPA 和 Hibernate 特定的异常,并将其转换为一系列集中的运行时异常。这让你仅在适当的层处理大多数不可恢复的持久性异常,而无需在 DAO 中编写令人厌烦的样板捕获和抛出块及异常声明。(你仍然可以在任何需要的地方捕获和处理异常。)如上所述,JDBC 异常(包括特定于数据库的方言)也转换为相同的层次结构,这意味着你可以在一致的编程模型中对 JDBC 执行某些操作。
In addition to JDBC exceptions, Spring can also wrap JPA- and Hibernate-specific exceptions, converting them to a set of focused runtime exceptions. This lets you handle most non-recoverable persistence exceptions in only the appropriate layers, without having annoying boilerplate catch-and-throw blocks and exception declarations in your DAOs. (You can still trap and handle exceptions anywhere you need to though.) As mentioned above, JDBC exceptions (including database-specific dialects) are also converted to the same hierarchy, meaning that you can perform some operations with JDBC within a consistent programming model.
上述讨论适用于 Spring 支持各种 ORM 框架中各种模板类。如果你使用基于拦截器的类,那么应用程序必须注意自行处理 HibernateExceptions
和 PersistenceExceptions
,最好分别委派给 SessionFactoryUtils
的 convertHibernateAccessException(..)
或 convertJpaAccessException(..)
方法。这些方法将异常转换为与 org.springframework.dao
异常层次结构中的异常兼容的异常。由于 PersistenceExceptions
未受检,因此也可以抛出它们(但在异常方面牺牲了通用的 DAO 抽象)。
The preceding discussion holds true for the various template classes in Spring’s support
for various ORM frameworks. If you use the interceptor-based classes, the application must
care about handling HibernateExceptions
and PersistenceExceptions
itself, preferably by
delegating to the convertHibernateAccessException(..)
or convertJpaAccessException(..)
methods, respectively, of SessionFactoryUtils
. These methods convert the exceptions
to exceptions that are compatible with the exceptions in the org.springframework.dao
exception hierarchy. As PersistenceExceptions
are unchecked, they can get thrown, too
(sacrificing generic DAO abstraction in terms of exceptions, though).
下图显示了 Spring 提供的异常层次结构。(请注意,图片中详述的类层次结构仅显示 DataAccessException
整个层次结构的一部分。)
The following image shows the exception hierarchy that Spring provides.
(Note that the class hierarchy detailed in the image shows only a subset of the entire
DataAccessException
hierarchy.)
Annotations Used to Configure DAO or Repository Classes
保证你的数据访问对象 (DAO) 或存储库提供异常转换的最佳途径是使用 @Repository
注解。该注解还允许组件扫描支持在不必须为其提供 XML 配置项的情况下查找和配置 DAO 和存储库。下例显示了如何使用 @Repository
注解:
The best way to guarantee that your Data Access Objects (DAOs) or repositories provide
exception translation is to use the @Repository
annotation. This annotation also
lets the component scanning support find and configure your DAOs and repositories
without having to provide XML configuration entries for them. The following example shows
how to use the @Repository
annotation:
- Java
-
@Repository (1) public class SomeMovieFinder implements MovieFinder { // ... }
1 | The @Repository annotation.
|
2 | The @Repository annotation. |
根据所使用持久性技术,任何 DAO 或存储库实现都需要访问持久性资源。例如,基于 JDBC 的存储库需要访问 JDBC 的 DataSource
,而基于 JPA 的存储库需要访问 EntityManager
。实现这一目标的最简单方法是使用 @Autowired
、@Inject
、@Resource
或 @PersistenceContext
注解之一注入此资源依赖项。下例适用于 JPA 存储库:
Any DAO or repository implementation needs access to a persistence resource,
depending on the persistence technology used. For example, a JDBC-based repository
needs access to a JDBC DataSource
, and a JPA-based repository needs access to an
EntityManager
. The easiest way to accomplish this is to have this resource dependency
injected by using one of the @Autowired
, @Inject
, @Resource
or @PersistenceContext
annotations. The following example works for a 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
,如下例所示:
If you use the classic Hibernate APIs, you can inject SessionFactory
, as the following
example shows:
-
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
:
The last example we show here is for typical JDBC support. You could have the DataSource
injected into an initialization method or a constructor, where you would create a JdbcTemplate
and other data access support classes (such as SimpleJdbcCall
and others) by using this
DataSource
. The following example autowires a 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)
// ...
}
请参阅每种持久性技术的具体 coverage 以了解如何配置应用程序上下文来利用这些注释。 |
See the specific coverage of each persistence technology for details on how to configure the application context to take advantage of these annotations. |