使用DAO ( Data Access Object ,数据访问对象)设计模式,以便将低级别的数据访问逻辑与高级别的业务逻辑分离。
Spring中的DAO层能够以一致的方式轻松处理JDBC 、Hibernate或JPA等数据的访问技术,这使得可以相当容易地在上述持久化技术之间进行切换。
同时,Spring 的DAO层对各种技术的异常进行了封装,以便开发者能够使用统一的异常,而无须担心捕捉每种技术特有的异常。
一致性异常层次结构
Spring将特定于技术的异常(如SQLException),统一转换为其自己的异常类层次结构,并将DataAccessException作为根异常以方便转换。这些异常包装了原始异常,因此不会丢失原始异常的出错信息。
除了JDBC异常外,Spring还可以封装Hibernate特定的异常,将它们转换为一组专注的运行时的异常(对于JPA 异常也是如此)。这使得开发过程变得简便了,因为无须在DAO中编写烦琐的catch-and-throw代码块和异常声明。同时,JDBC异常(包括特定于数据库的方言)由于已经转换为相同的层次结构,这意味着可以在一致的编程模型中使用JDBC 的执行操作。
以上列举的Spring的各种模板类支持各种ORM 框架。如果使用基于拦截器的类,那么程序必须关心并处理HibernateExceptions和PersistenceExceptions本身,最好是通过分别授权给SessionFactoryUtils的convertHibernateAccessException( .. ) 或convertJpaAccessException()方法。这些方法将异常转换为与org.spri ngframework. dao中异常层级兼容的异常。由于PersistenceExceptions 没有被检查,它可以被简单地抛出,这也牺牲了DAO在异常上的抽象。
DAO和repository类注解
在领域驱动设计( Domain-Driven Design, DDD )领域,与数据存储交互的领域概念被称为存储库( Repository ) 。所以在Spring框架中,使用@Repository注解来表示DAO 层是最合适不过的。
该注解还允许组件扫描查找和配置DAO及存储库,而无须为它们提供XML 配置条目。
@Repository
public class SomeMovieFinder implements MovieFinder {
// ...
}
任何DAO或存储库的实现都需要访问持久性资源,具体取决于所使用的持久化技术。例如,基于JDBC的存储库需要访问JDBC数据源,而基于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
@Repository
public class JdbcMovieFinder implements MovieFinder {
private JdbcTemplate jdbcTemplate;
@Autowired
public void init(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// ...
}