Spring 框架参考文档(四)-数据访问之(DAO 支持)
这部分参考文档介绍有关于数据访问和数据访问层和业务层或服务层之间的相互作用.
spring的综合事务管理支持也在一些地方被提到, 就在介绍了Spring Framework支持集成的大量数据访问框架 和技术之后.
- Chapter 11, 事务管理
- Chapter 12, DAO 支持
- Chapter 13, Data access with JDBC
- Chapter 14, 对象关系映射(ORM)数据访问
- Chapter 15, Marshalling XML using O/X Mappers
12. DAO 支持
12.1 介绍
Spring中对数据访问对象(DAO)的支持旨在简化Spring与数据访问技术的操作,使JDBC、Hibernate、JPA和JDO等采用统一的方式访问。 这就允许使用者在各种持久化技术之间能够相对轻松的进行切换,同时,使用者也不必担心每种不同技术造成的异常处理的差异。
12.2 一致的异常层次结构
Spring提供了一个方便地从特定技术异常(如SQLException
)转换为以DataAccessException
作为根异常的自身异常层次结构中的类。 异常层次结构中的类将原始异常进行了包装,所以,我们不用担心发生错误后异常信息丢失的问题。
除了JDBC异常以外,Spring也可以包装特定的Hibernate异常,可以将所有的checked异常(支持Hibernate 3.0以前的版本)转换为 一组集中的运行时异常,JDO和JPA异常也可以同样包装。这就允许使用者不必在DAO中写大量的烦人的死板的catch和throw语句以及对 应的异常声明 ,就可以处理绝大多数不可恢复的只能在特定层处理的持久化异常。(使用者也还可以再需要的地方捕获和处理异常。) 如上所述,JDBC异常(包括特定的数据库方言)也会转换为同样的级别,这就意味着使用者可以使用一个一致的编程模型来使用JDBC。
Spring支持的各种ORM框架的模板类都支持上面的特性。如果使用者基于拦截器的类,那么程序必须关心如何处理HibernateExceptions
和JDOExceptions
异常, 最好是分别委托给SessionFactoryUtils
的convertHibernateAccessException(..)
或convertJdoAccessException()
方法。这两个方法可以将异常转换为与org.springframework.dao
异常层次结构相兼容的异常类。就异常而言,虽然牺牲了通用的DAO抽象特性,但因为JDOExceptions
异常是unchecked,它们也可以被简单的抛出。 Spring提供的异常层次结构如下图所示。(请注意图中的类层次结构只是整个DataAccessException
的一个子集。)
12.3 用于配置DAO或库类的注解
确保自定义的数据访问对象(DAO)或库类提供的异常转换的最好方法就是使用@Repository
注解。这一注解同样允许组件扫描来发现和配置自定义DAO和库,而不用提供XML配置信息。
@Repository public class SomeMovieFinder implements MovieFinder { // ... }
任何DAO或者库实现都依赖所使用的持久化技术来需要访问某个持久化资源;例如,一个基于JDBC的库需要访问一个JDBC数据源DataSource
;一个基于JPA的库需要访问一个EntityManager
。 完成这一操作的最简单的方式使用@Autowired,
, @Inject
, @Resource
或@PersistenceContext
等这样的资源依赖注入的注解。下面有一个JPA库的例子:
@Repository public class JpaMovieFinder implements MovieFinder { @PersistenceContext private EntityManager entityManager; // ... }
如果你使用了经典Hibernate的API,那么就可以注入SessionFactory:
@Repository public class HibernateMovieFinder implements MovieFinder { private SessionFactory sessionFactory; @Autowired public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } // ... }
在最后一个例子中,我们将介绍对典型JDBC的支持。你可以将DataSource
注入到已创建的JdbcTemplate
的初始化方法中,然后其他数据访问支持类(如SimpleJdbcCall
等)就可以使用这个数据源DataSource
了。
@Repository public class JdbcMovieFinder implements MovieFinder { private JdbcTemplate jdbcTemplate; @Autowired public void init(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } // ... }