通用 ORM 集成注意事项
本节重点介绍适用于所有 ORM 技术的注意事项。 Hibernate 部分提供了更多详细信息,并在具体上下文中展示了这些功能和配置。
Spring 的 ORM 集成的主要目标是明确的应用程序分层(使用任何数据访问和事务技术)以及应用程序对象的松耦合——不再有业务服务对数据访问或事务策略的依赖,不再有硬编码的资源查找,不再有难以替换的单例,不再有自定义服务注册表。目标是采用一种简单一致的方法来连接应用程序对象,使它们尽可能地可重用且不受容器依赖。所有单独的数据访问功能都可以独立使用,但可以很好地与 Spring 的应用程序上下文概念集成,提供基于 XML 的配置和需要无需 Spring 感知的普通 JavaBean 实例的交叉引用。在一个典型的 Spring 应用程序中,许多重要的对象都是 JavaBean:数据访问模板、数据访问对象、事务管理器、使用数据访问对象和事务管理器的业务服务、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 自定义异常层次结构的透明异常转换(如果需要)。