通用 ORM 集成注意事项
本节重点介绍适用于所有 ORM 技术的注意事项。Hibernate 部分提供了更多详细信息,并在具体上下文中展示了这些功能和配置。
Spring 的 ORM 集成的主要目标是实现清晰的应用程序分层(使用任何数据访问和事务技术)以及应用程序对象的松耦合——不再有业务服务对数据访问或事务策略的依赖,不再有硬编码的资源查找,不再有难以替换的单例,不再有自定义服务注册表。目标是拥有一种简单且一致的方法来连接应用程序对象,使它们尽可能可重用且不依赖于容器。所有单独的数据访问功能都可以独立使用,但可以很好地与 Spring 的应用程序上下文概念集成,提供基于 XML 的配置和普通 JavaBean 实例的交叉引用,这些实例无需了解 Spring。在典型的 Spring 应用程序中,许多重要的对象都是 JavaBeans:数据访问模板、数据访问对象、事务管理器、使用数据访问对象和事务管理器的业务服务、Web 视图解析器、使用业务服务的 Web 控制器等等。
资源和事务管理
典型的业务应用程序充斥着重复的资源管理代码。许多项目尝试发明自己的解决方案,有时为了编程的便利性而牺牲了对失败的正确处理。Spring 提倡通过简单的解决方案来进行适当的资源处理,即在 JDBC 的情况下通过模板化实现 IoC,并对 ORM 技术应用 AOP 拦截器。
基础设施提供了适当的资源处理和将特定 API 异常转换为未检查的基础设施异常层次结构的功能。Spring 引入了一个适用于任何数据访问策略的 DAO 异常层次结构。对于直接 JDBC,前一节中提到的 JdbcTemplate
类提供了连接处理和将 SQLException
适当转换为 DataAccessException
层次结构的功能,包括将数据库特定的 SQL 错误代码转换为有意义的异常类。对于 ORM 技术,请参见下一节以了解如何获得相同的异常转换优势。
在事务管理方面,JdbcTemplate
类与 Spring 事务支持相结合,并通过相应的 Spring 事务管理器支持 JTA 和 JDBC 事务。对于支持的 ORM 技术,Spring 通过 Hibernate 和 JPA 事务管理器以及 JTA 支持提供 Hibernate 和 JPA 支持。有关事务支持的详细信息,请参见事务管理章节。
异常转换
当你在 DAO 中使用 Hibernate 或 JPA 时,必须决定如何处理持久化技术的原生异常类。DAO 会抛出 HibernateException
或 PersistenceException
的子类,具体取决于所使用的技术。这些异常都是运行时异常,不需要声明或捕获。你可能还需要处理 IllegalArgumentException
和 IllegalStateException
。这意味着调用者只能将异常视为一般性的致命错误,除非他们想依赖于持久化技术自身的异常结构。捕获特定原因(例如乐观锁定失败)是不可能的,除非将调用者与实现策略绑定。这种权衡对于那些强烈基于 ORM 的应用程序或不需要任何特殊异常处理的应用程序(或两者)可能是可以接受的。然而,Spring 允许通过 @Repository
注解显式地应用异常转换。以下示例(一个用于 Java 配置,一个用于 XML 配置)展示了如何实现这一点:
- Java
- Kotlin
@Repository
public class ProductDaoImpl implements ProductDao {
// class body here...
}
@Repository
class ProductDaoImpl : ProductDao {
// class body here...
}
<beans>
<!-- Exception translation bean post processor -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>
后处理器会自动查找所有异常转换器(PersistenceExceptionTranslator
接口的实现),并通知所有用 @Repository
注解标记的 bean,以便发现的转换器可以拦截并对抛出的异常应用适当的转换。
总之,您可以基于简单持久化技术的 API 和注解来实现 DAO,同时仍然可以受益于 Spring 管理的事务、依赖注入以及透明的异常转换(如果需要)到 Spring 的自定义异常层次结构。