简介
spring在资源管理,dao实现支持以及实物策略等方面提供了与hibernate, jdo和ibatis sql映射的集成。 对hibernate,spring使用了很多ioc的方便的特性提供了一流的支持,帮助你处理很多典型的hibernate整合的问题。所有的这些都遵守spring通用的事务和dao异常体系。
当您选择使用o/r映射来创建数据访问应用程序的时候,spring的增加部分就会向您提供重要的支持。首先你应该了解的是,一旦你使用了spring对o/r映射的支持,你不需要亲自作所有的事情。在决定花费力气,冒着风险建造类似的内部底层结构之前,我们都建议您考虑和利用spring的解决方案。不管你使用的是何种技术,大部分的o/r映射支持都可以以library样式被使用,因为所有的东西都是被设计成一组可重复利用的javabeans。在applicationcontext和beanfactory中使用更是提供了配置和部署简单的好处,因此,这一章里的大多数例子都是在applicationcontext中配置。
使用spring构建你的orm应用的好处包括:
l 避免绑定特殊的技术,允许mix-and-match的实现策略。虽然hibernate非常强大,灵活,开源而且免费,但它还是使用了自己的特定的api。此外有人也许会争辩:ibatis更轻便而且在不需要复杂的o/r映射策略的应用中使用也很优秀。能够选择的话,使用标准或抽象的api来实现主要的应用需求,通常是更好的。尤其,当你可能会因为功能,性能或其他方面的原因而需要切换到另一个实现的时候。举例来说,spring对hibernate事务和异常的抽象,以及能够让你轻松交换mapper和dao对象(实现数据访问功能)的ioc机制,这两个特性可以让你在不牺牲hibernate性能的情况下,在你的应用程序中隔离hibernate的相关代码。处理dao的高层次的service代码不需要知道dao的具体实现。这个方法可以很容易使用mix-and-match方案互不干扰地实现数据访问层(比如在一些地方用hibernate,一些地方使用jdbc,其他地方使用ibatis),mix-and-match有利于处理遗留下来的代码以及利用各种技术(jdbc,hibernate,ibatis)的长处。
测试简单
spring的ioc使得很容易替换掉不同的实现,hibernate sessionfacotory的位置,datasource, 事务管理, 映射对象的实现。这样就很容易隔离测试持久化相关代码的各个部分。
l 普通的资源管理。spring的application context能够处理诸如hibernate 的sessionfactory, jdbc的datasource,ibatis的sqlmaps配置对象以及其他相关资源的定位和配置。这使得这些配置的值很容易被管理和修改。spring提供了有效,简单和安全的hibernate session处理。一般的使用hibernate的代码则需要使用同一个hibernate session对象以确保有效和恰当地事务处理。而spring让我们可以很容易透明地创建和绑定一个session到当前线程;你可以使用以下两种办法之一:声明式的aop方法拦截器,或通过使用一个外部的template包装类在java代码层次实现。这样,spring就解决了在很多hibernate论坛上出现的使用问题。
异常包装
spring能够包装hibernate异常,把它们从专有的,checked exception变为一组抽象的runtime exception。这样你就可以仅仅在恰当的层处理大部分的不可恢复的异常,使你避免了很多讨厌的catch/throw以及异常声明。你还是可以在你需要的地方捕捉和处理异常。回想一下jdbc异常(包括与db相关的方言)被转变为同样的异常体系,这就意味着你可以在一致的编程模型中处理jdbc操作。
l 综合的事务管理。spring允许你包装你的orm代码,通过使用声明式的aop方法拦截器或者在代码级别使用外部的template包装类。不管使用哪一种,事务相关的语义都会为你处理,万一有异常发生也会帮你做适当的事务操作(比如rollback)。就象我们下面要讨论的一样,你能够使用和替换各种transaction managers,却不会使你的hibernate相关的代码受到影响。更好的是,jdbc相关的代码可以完全和hibernate代码integrate transactionaly。这对于处理那些没有用hibernate或ibatis实现的功能非常有用。
1.2.hibernate
1.2.1.资源管理
典型的应用经常会被重复的资源管理代码搞胡乱。很多项目尝试创造自己的方案解决这个问题,有时会为了编程方便牺牲适当的故障处理。对于恰当的资源处理spring提倡令人瞩目的简单的解决方案:使用templating的ioc,比如基础的class和回调接口,或者提供aop拦截器。基础的类负责固定的资源处理,以及将特定的异常转换为unchecked异常体系。spring引进了dao异常体系,可适用于任何数据访问策略。
对于直接使用jdbc的情况,前面章节提到的jdbctemplate类负责处理connection,正确地把sqlexeption变为dataaccessexception体系(包括将与数据库相关的sql错误代码变成有意义的异常类)。它同时支持jta和jdbc事务,通过它们各自的spring transaction managers。
spring同样也提供了对hibernate和jdo的支持:一个hibernatetemplate/jdotemplate类似于jdbctemplate,hibernateinterceptor/jdointerceptor,以及一个hibernate/jdo transaction manager。主要的目的是:能够清晰地划分应用层次而不管使用何种数据访问和事务技术;使应用对象之间的耦合松散。业务对象(bo)不再依赖于数据访问和事务策略;不再有硬编码的资源lookup;不再有难于替换的singletons;不再有自定义的服务注册。一个简单且坚固的方案连接了应用对象,并且使它们可重用尽可能地不依赖容器。虽然所有的数据访问技术都能独立使用,但是与spring application context结合更好一些,它提供了基于xml的配置和普通的与spring 无关的javabean实例。在典型的spring app中,很多重要的对象都是javabeans:数据访问template,数据访问对象(使用template),transaction managers, 业务对象(使用数据访问对象和transaction managers),web view resolvers, web controller(使用业务对象)等等。
1.2.2.在application context中定义资源
为了避免将应用对象贴紧硬编码的资源lookup,spring允许你像定义普通bean一样在application context中定义诸如jdbc datasource,hibernate sessionfactory的资源。需要访问这些资源的应用对象只需要持有这些预定义实例的引用。下面的代码演示如何创建一个jdbc datasource和hibernate sessionfactory:
<beans>
<bean id="mydatasource"
class="org.springframework.jndi.jndiobjectfactorybean">
<property name="jndiname">
<value>java:comp/env/jdbc/myds</value>
</property>
</bean>
<bean id="mysessionfactory"
class="org.springframework.orm.hibernate.localsessionfactorybean">
<property name="mappingresources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateproperties">
<props>
<prop key="hibernate.dialect">
net.sf.hibernate.dialect.mysqldialect
</prop>
</props>
</property>
<property name="datasource">
<ref bean="mydatasource"/>
</property>
</bean>
……
</beans>
你可以将一个jndi定位的datasource换为一个本地定义的如dbcp的basicdatasource,如下面的代码:
<bean id="mydatasource" class="org.apache.commons.dbcp.basicdatasource"
destroy-method="close">
<property name="driverclassname">
<value>org.hsqldb.jdbcdriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:hsql://localhost:9001</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
当然你也可以把本地的sessionfactory换为jndi定位的,但是如果不是在ejb上下文中,这是不需要的。(查看“容器资源 vs 本地资源”一节)
1.2.3.反转控制:template和callback
对于可以成为定制的数据访问对象或业务对象的方法来说,基本的模板编程模型看起来像下面所示的代码那样。对于外部对象没有任何实现特定接口的要求,它只需要提供一个hibernate的sessionfacotry。它可以从任何地方得到,比较适宜的方法是作为从spring 的application context中得到的bean引用:通过简单的setsessionfactory这个bean属性setter。下面的代码显示了在application context中一个dao的定义,它引用了上面定义的sessionfactory,同时展示了一个dao方法的具体实现。
<beans>
<bean id=”myproductdao” class=”product.productdaoimpl”>
<property name=”sessionfactory”>
<ref bean=”mysessionfactory”/>
</property>
</bean>
….
</beans>
public class productdaoimpl implements productdao{
private sessionfactory sessionfactory;
public void setsessionfactory(sessionfactory sessionfactory) {
this.sessionfactory = sessionfactory;
}
public list loadproductsbycategory(final string category) {
hibernatetemplate hibernatetemplate =
new hibernatetemplate(this.sessionfactory);
return (list) hibernatetemplate.execute(
new hi
闽公网安备 35060202000074号