) 介绍
最近我参与了北美一家银行的审计系统的后台软件设计和开发工作除了使用Web Service以外我们集成了Spring和Hibernate通过Spring的HibernateTemplate实现了对数据库数据的存取众所周知Hibernate是一种广泛应用的一种强大的数据持久层技术 另一方面Spring作为支持IOC的依赖注入框架 其优点是能够非常好地集成大多数主流技术 本文我们将讨论如何集成 Spring 和Hibernate
) Spring和Hibernate基础
在我们实际进入集成这两个技术之前让我们理解这种集成需求大家都知道Hibernate是一种位于应用和数据库之间的强大的ORM 工具 它可使应用以独立平台的方式从各种数据库访问数据对应用来说没有必要依赖于低级DBC 细节如管理连接 处理statements 和result sets 所有访问特定数据源的细节很容易在Xml文件中配置另一个好处是Hibernate和JSE和JEE应用兼容得很好
使用Hibernate 问题之一是使用Hibernate Framework访问数据库的客户应用必须依赖Hibernate APIs如Configuration SessionFactory and Session 这些个对象在应用代码中持续扩散而且应用代码必须用手工维护和管理这些对象但是在Spring的环境 业务对象通过IOC的帮助下是能够通过配置完成的简单地说一个对象状态能够从应用代码中分离意思是现在使用Hibernate 对象作为Spring Beans是可能的他们能够得到Spring提供的所有方便
) 集成Sample
我们没有打算研究Spring包里集成的各种API我们想通过实例源码来学习和理解这些APIs 下列部分包括了集成SpringHiberante 的每个步骤并附有详细的解释
) 创立数据库
下面的应用使用Oracle数据库 Oracleg的express版本可以从免费下载安装后 先用管理员身份登录和创建用户schemausername and password再以用户身份登录后去SQL command 或SQL Script运行以下SQL statement create table Activitylog(id varchar() name varchar() taskcode varchar() tasktime timestamp)现在一个空表已创立
) ActivityLog类
现在让我们创建叫做Activitylog POJO代码用于存储从Activitylog表取出的数据此类的设计使表Activitylog的列名将被映射到Java类Activitylog适当类型的变量名 可使用ant工具或plugin产生Activitylog类完整的代码列举如下
packagecomxxxauditpojo;
publicclassActivitylog{
privateStringid;
privateStringname;
privateStringtaskcode;
privateTimestamptasktime;
publicActivitylog(){
}
publicStringgetId(){
returnid;
}
publicvoidsetId(Stringid){
thisid=id;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
thisname=name;
}
publicStringgetTaskcode(){
returntaskcode;
}
publicvoidsetTaskcode(Stringtaskcode){
thistaskcode=taskcode;
}
publicTimestampgetTasktime(){
returntasktime;
}
publicvoidsetTasktime(Timestamptasktime){
thistasktime=tasktime;
}
publicStringtoString(){
returnId=+id+Name=+name+Taskcode=
+taskcode+Tasktime=+tasktime;
}
}
注意toString() 方法重写是为了Activitylog 对象的显示
) 创建Hibernate Mapping 文件
我们已经在数据库中创建了Activitylog 表和一个在应用层相应的Java类 class我们需要创建Hibernate Mapping文件去把Activitylog 表映射到Activitylog Java 类Activitylog 表的列名映射到Activitylog Java 类的变量可使用ant工具或plugin产生让我们看看Hibernate Mapping文件
Activityloghbmxml
<?xmlversion=?>
<!DOCTYPEhibernatemappingPUBLIC//Hibernate/HibernateMappingDTD//EN
mappingdtd>
<hibernatemapping>
<classname=comxxxxauditpojoactivitylogtable=activitylog>
<idname=idcolumn=Id>
<generatorclass=assigned/>
</id>
<propertyname=name>
<columnname=Name/>
</property>
<propertyname=taskcode>
<columnname=Taskcode/>
</property>
<propertyname=tasktime>
<columnname=Tasktime/>
</property>
</class>
</hibernatemapping>
注意映射文件是一个Xml文件并且它的名字是Activityloghbmxml 文件名中hbm 代表它是Hibernate映射文件 class 标记定义了数据库表和Java类之间的映射 name 属性必须指向一个全路径的Java类名反之表属性必须指向数据库表接下来的标记定义了列名和对应java变量之间的映射id 标记作为主键定义了一行的标识property标记有一个属性叫name 指向Java变量名 接下来的是它映射的数据库表的列名
) 创立Spring配置文件
这部分处理配置各种Spring需要的信息 在Spring全部的业务对象在Xml文件中配置配置的业务对象叫做 Spring Beans这些Spring Beans可通过IOC维护让我们定义一个data source如下
springhibernatexml
<?xmlversion=encoding=UTF?>
<beansxmlns=
xmlns:xsi=instance
xsi:schemaLocation=;
beansxsd>
<beanid=myDataSourceclass=monsdbcpBasicDataSource>
<propertyname=driverClassNamevalue=oraclejdbcdriverOracleDriver/>
<propertyname=urlvalue=jdbc:oracle:thin:@localhost::XE/>
<propertyname=usernamevalue=root/>
<propertyname=passwordvalue=root/>
</bean>
?
</beans>
上面bean定义了一个类型monsdbcpBasicDataSource的datasource 更重要的是 它定义了各种访问数据库所需要的连接属性
现在让我们定义第二个Spring BeanSessionFactory如果你有Hibernate编程经验 你将实现SessionFactory Bean 负责去创建Session对象通过Session对象处理 Transaction 和数据访问 现在同样的SessionFactory Bean必须用Spring的方式进行配置如下
<beanid=mySessionFactory
class=orgspringframeworkormhibernateLocalSessionFactoryBean>
<propertyname=dataSourceref=myDataSource/>
<propertyname=mappingResources>
<list>
<value>com/xxxx/audit/pojo/Activityloghbmxml</value>
</list>
</property>
<propertyname=hibernateProperties>
<value>hibernatedialect=orghibernatedialectOracleDialect</value>
</property>
</bean>
当配置SessionFactory Bean时我们已经给出两个强制信息 一个是datasource 信息包含访问数据库的细节第二个是一个映射文件的列表他包含了数据库表和Java类之间的映射信息我们在第部分已经定义了他们在list标志中应用
第三个重要的Spring Bean是Hibernate Template 它提供了一个低级数据访问和操作的包装精确地它包含以下方法insert/delete/update/find数据库中的数据对Hibernate Template的配置唯一的变量是SessionFactory Bean对象如下所示
<beanid=hibernateTemplate
class=orgspringframeworkormhibernateHibernateTemplate>
<propertyname=sessionFactory>
<refbean=mySessionFactory/>
</property>
</bean>
最后的Bean定义是Dao类是客户化的类 虽然此类必须定义在应用级它能够包含任意数量客户数据访问方法的封装虽然我们知道它是与数据库交互的 Hibernate Template类它将是一个Hibernate Template的理想引用
<beanid=ActivitylogDaoclass=javabeatspringhibernateActivitylogDao>
<propertyname=hibernateTemplate>
<refbean=hibernateTemplate/>
</property>
</bean>
注意一个引用指向 ActivitylogDao类它是我们以前讨论过的
)定义ActivitylogDao class
如上所述 这个ActivitylogDao 类能够包含任意数量的方法供客户访问这个类的设计有两种选择第一种是此类能够直接依赖Hibernate Template 对象访问数据它由IOC注入 第二种是它你呢个够利用Hibernate API做数据访问此类声明如下
ActivitylogDaojava
packagejavabeatspringhibernate;
importjavasqlSQLException;
importorghibernateHibernateException;
importorghibernateSession;
importorgspringframeworkormhibernateHibernateCallback;
importorgspringframeworkormhibernateHibernateTemplate;
publicclassActivitylogDao{
privateHibernateTemplatehibernateTemplate;
publicvoidsetHibernateTemplate(HibernateTemplatehibernateTemplate){
thishibernateTemplate=hibernateTemplate;
}
publicHibernateTemplategetHibernateTemplate(){
returnhibernateTemplate;
}
publicActivityloggetActivitylog(finalStringid){
HibernateCallbackcallback=newHibernateCallback(){
publicObjectdoInHibernate(Sessionsession)
throwsHibernateExceptionSQLException{
returnsessionload(Activitylogclassid);
}
};
return(Activitylog)hibernateTemplateexecute(callback);
}
publicvoidsaveOrUpdate(finalActivitylogactivitylog){
HibernateCallbackcallback=newHibernateCallback(){
publicObjectdoInHibernate(Sessionsession)
throwsHibernateExceptionSQLException{
sessionsaveOrUpdate(activitylog);
returnnull;
}
};
hibernateTemplateexecute(callback);
}
}
此类利用了Hibernate API (特别是Session对象) 用于数据访问引导Spring访问 Hibernate API 我们把逻辑细化利用Hibernate API 融入Spring知道的着名接口中的特别着名的方法 It happens to be the HibernateCallback 接口使用方法doInHibernate() 通过传送一个Hibernate Session 实例 ActivitylogDao类我们已经定义了两个方法getActivitylog () and saveOrUpdate 使用Hibernate APIs 我们定义了HibernateCallback中的代码 doInHibernate() 方法和通知Spring 执行这些代码 传送接口引用HibernateTemplateexecute() 方法
) 客户端测试程序
SpringHibernateTestjava
packagejavabeatspringhibernate;
importorgspringframeworkbeansfactoryBeanFactory;
importorgspringframeworkbeansfactoryxmlXmlBeanFactory;
importorgreioFileSystemResource;
importorgreioResource;
importorgspringframeworkormhibernateLocalSessionFactoryBean;
publicclassSpringHibernateTest{
publicstaticvoidmain(String[]args){
Resourceresource=newFileSystemResource(/springhibernatexml);
BeanFactoryfactory=newXmlBeanFactory(resource);
Activitylogactivitylog=newActivitylog();
activitylogsetId();
activitylogsetName(ABC);
activitylogsetTaskcode();
activitylogsetTasktime(::);
ActivitylogDaoactivitylogDao=(ActivitylogDao)factorygetBean(
activitylogDao);
activitylogDaosaveOrUpdate(activitylog);
ActivitylogactResult=activitylogDaogetActivitylog();
Systemoutprintln(actResult);
}
}
最后 我们运行客户应用访问测试数据过程像这样 当方法BeanFactorygetBean(ActivitylogDao) 被调用 Spring 找到ActivitylogDao Bean 的指针 它产生Hibernate Template 对象 然后初始化Hibernate Template对象 我们将看到一个Session Factory Bean对象被引用然后当建立Session Factory Bean对象的时候 将得到datasource 信息和数据库表和Java类
)总结
本文讨论了Spring 和Hibernate的集成 既讨论了需求也讨论了它带来的好处 通过一个详细的实例一步步清晰地演示了集成工作