分享
 
 
 

Spring 系列:当 Hibernate 遇上 Spring

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

Naveen Balani 继续他的 SPRing 系列,介绍把 Hibernate 事务与 Spring 面向方面编程(AOP)集成的知识。结果是一个可以依靠的持久性框架。

在这个系列的 前一期中,我介绍了 Spring 框架的 7 个模块,包括 Spring AOP 和控制反转(IOC)容器。然后我用一个简单的示例演示了 IOC 模式(由 Spring IOC 容器实现)如何用松散耦合的方式集成分散的系统。

现在,我从我上次结束的地方开始,采用与上次类似的示例,演示 Spring AOP 和 Spring Hibernate 持久性支持的声明性事务处理,所以我首先从对这两项技术的深入研究开始。

下载这篇文章的源代码。请参阅 参考资料 访问 Spring 框架和 Apache Ant,运行这篇文章的示例应用程序需要它们。

Spring AOP

软件系统通常由多个组件构成,每个组件负责一个特定的功能领域。但是,这些组件也经常承担它们的核心功能之外的额外责任。系统服务(例如日志、事务管理和安全性)经常发现自己跑到了别的组件的领域里,而这些组件的核心职责是其他事情。结果就是所谓的“代码纠缠”,或者更简单点儿说“一团糟”。面向方面编程是一种试图解决这个问题的编程技术,它把关注点的隔离提升为核心的编程概念。

使用 AOP 时,仍然是在一个地方定义系统的公共功能,但是可以声明性地定义 如何 和 在哪里 应用这个功能。如果对横切关注点(例如日志和事务管理)进行了模块化,那么不用修改每个单独的类,就可以向代码中添加新特性。这类模块化的关注点称作 方面。

您知道么?

可以在任何 java™ 企业版(J2EE) 服务器中使用 Spring 框架的功能。而且,还可以调整它的大多数功能,使其适合不受控环境。Spring 的中心焦点就是支持不被束缚在特定 J2EEE 服务上的可重用业务和数据访问对象。可以跨 J2EE 环境(Web 或企业 JavaBean(EJB))、独立应用程序、测试环境等等重用这类对象,而不会有任何麻烦。

以一个企业应用程序为例。这类应用程序通常要求类似于安全性和事务支持的服务。显然,可以把这些服务的支持直接编写到要求服务的每个类当中,但是更希望能够不必为大量事务性上下文编写同样的事务处理代码。如果使用 Spring AOP 进行事务处理,那么可以声明性地安排适当的方法调用,而不必逐个安排。

Spring AOP 提供了几个方面,可以为 JavaBean 声明事务。例如,TransactionProxyFactoryBean 是个方便的代理类,能够拦截对现有类的方法调用,并把事务上下文应用到事务 bean。在下面的示例中会看到这个类的实际应用。

回页首

Hibernate

Spring 框架提供了对 Hibernate、JDO 和 iBATIS SQL Maps 的集成支持。Spring 对 Hibernate 的支持是第一级的,整合了许多 IOC 的方便特性,解决了许多典型的 Hibernate 集成问题。框架对 Hibernate 的支持符合 Spring 通用的事务和数据访问对象(DAO)异常层次结构。

Spring 为使用选择的 OR 映射层来创建数据访问应用程序提供了支持。因为所有东西都设计成一组可重用 JavaBean,所以不管选择什么技术,都能以库的格式访问大多数 Spring 的 OR 映射支持。 applicationContext 或 BeanFactory 内部的 OR 映射的好处是简化了配置和部署。

Hibernate 是 Java 平台上一个功能全面的、开源的 OR 映射框架。Hibernate 支持开发符合常规 Java 理念的持久性类 —— 包括关联、继承、多态、复合以及 Java 集合框架。Hibernate 查询语言(HQL)被设计成 SQL 的一个微型面向对象扩展,它是对象和关系世界之间的桥梁。Hibernate 也支持用原始 SQL 或基于 Java 的标准和示例查询表达查询。Hibernate 使用 xml(*.hbm.xml) 文件把 Java 类映射到表,把 JavaBean 属性映射到数据库表。

通过 JDBC 技术,支持所有的 SQL 数据库管理系统。Hibernate 与所有流行的 J2EE 应用程序服务器和 Web 容器都很好地集成。

回页首

实际示例

一个银行应用程序示例可以让您自己看到 Spring AOP 和 Hibernate 一起工作有多么好。银行帐户用例允许用户 (Customer) 在一个事务中打开一个或多个银行帐户。用户可以申请多个银行帐户,可以选择是支票帐户类型或者是储蓄帐户类型。

应用程序数据库(Cloudscape™)容纳所有客户和帐户信息。在这个例子中,假设在 Customer 和 Account 类之间存在 1:N 的关联。在实际生活场景中,关联可能需要按 m:n 建模,才能支持联合帐户。

由于用户必须可以在一个事务中申请多个帐户,所以首先要为数据库交互实现一个 DOA 模式。然后要设置 Spring AOP 的 TransactionProxyFactoryBean,让它拦截方法调用并声明性地把事务上下文应用到 DOA。

回页首

Hibernate 实践

在 Spring 框架中,像 JDBC DataSource 或 Hibernate sessionFactory 这样的资源,在应用程序上下文中可以用 bean 实现。需要访问资源的应用程序对象只需通过 bean 引用得到这类预先定义好的实例的引用即可(这方面的更多内容在 下一节中)。在清单 1 中,可以看到示例银行应用程序的一段摘录:XML 应用程序上下文定义显示了如何设置 JDBC DataSource,并在上面放一个 Hibernate SessionFactory。

清单 1. JDBC DataSource 和 HibernateSessionFactory 连接

<!-- DataSource Property -->

<bean id="exampleDataSource"

class="org.apache.commons.dbcp.BasicDataSource">

<property name="driverClassName">

<value>org.apache.derby.jdbc.EmbeddedDriver</value>

</property>

<property name="url">

<value>jdbc:derby:springexample;create=true</value>

</property>

</bean>

<!-- Database Property -->

<bean id="exampleHibernateProperties"

class="org.springframework.beans.factory.config.PropertiesFactoryBean">

<property name="properties">

<props>

<prop key="hibernate.hbm2ddl.auto">update</prop>

<prop

key="hibernate.dialect">net.sf.hibernate.dialect.DerbyDialect</prop>

<prop

key="hibernate.query.substitutions">true 'T', false 'F'</prop>

<prop key="hibernate.show_sql">false</prop>

<prop key="hibernate.c3p0.minPoolSize">5</prop>

<prop key="hibernate.c3p0.maXPoolSize">20</prop>

<prop key="hibernate.c3p0.timeout">600</prop>

<prop key="hibernate.c3p0.max_statement">50</prop>

<prop

key="hibernate.c3p0.testConnectionOnCheckout">false</prop>

</props>

</property>

</bean>

<!-- Hibernate SessionFactory -->

<bean id="exampleSessionFactory"

class="org.springframework.orm.hibernate.LocalSessionFactoryBean">

<property name="dataSource">

<ref local="exampleDataSource"/>

</property>

<property name="hibernateProperties">

<ref bean="exampleHibernateProperties" />

</property>

<!-- OR mapping files. -->

<property name="mappingResources">

<list>

<value>Customer.hbm.xml</value>

<value>Account.hbm.xml</value>

</list>

</property>

</bean>

清单 1 显示了如何为示例应用程序数据库(是 Cloudscape)配置数据源 bean (exampleDataSource)。exampleDatasource 被连接到 Spring Hibernate 的 SessionFactory。请注意 *.hbm.xml 指定了示例应用程序的 OR 映射文件。

数据源和会话工厂设置好之后,下一步就是在 DAO 中连接,在 CustomerDAOImpl 示例中,要使用 SessionFactory。接下来,插入 Spring 的 TransactionProxyFactoryBean,它会拦截对应用程序的 CustomerDAOImpl 对象的方法调用,并声明性地在它上面应用事务。

在 清单 2 的这个示例中,CustomerDAOImpl 类的 addCustomer 方法是作为事务的一部分执行的,有一个事务属性 PROPAGATION_REQUIRED。这个属性等价于 EJB 容器的 TX_REQUIRED。如果想让这个方法一直在事务中运行,可以使用 PROPAGATION_REQUIRED。如果事务已经在运行,那么 bean 方法会加入事务,否则 Spring 的轻量级事务管理器会启动一个事务。如果想在调用组件服务时总是启动新事务,可以使用 PROPAGATION_REQUIRES_NEW 属性。

应用程序的连接完成之后,现在来进一步查看源代码。

回页首

分析这个!

如果以前没这么做过,那么请 下载这篇文章的源代码。把源 zip 文件释放到计算机中的任何位置上,例如 c:\。会创建一个叫作 SpringProjectPart2 的文件夹。src\spring 文件夹包含示例应用程序的 Hibernate 映射文件和 Spring 配置文件。src\springexample\hibernate 文件包含应用程序的源代码。

在这里会发现两个类,即 Customer 和 Account,它们用 Hibernate 映射文件映射到两个表。Customer 类代表客户信息,Account 代表客户的帐户信息。正如前面提到的,我把这两个类按照 1: N 关系进行建模,即一个 Customer 可以拥有多个 Account。清单 3 显示了 Customer 对象的 Hibernate 映射文件。

清单 3. Customer 对象的 Hibernate 映射文件

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 2.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>

<class

name="springexample.hibernate.Customer"

table="TBL_CUSTOMER"

dynamic-update="false"

dynamic-insert="false">

<id

name="id"

column="CUSTOMER_ID"

type="java.lang.Long"

unsaved-value="-1"

>

<generator class="native">

</generator>

</id>

<set name ="accounts"

inverse = "true"

cascade="all-delete-orphan">

<key column ="CUSTOMER_ID"/>

<one-to-many class="springexample.hibernate.Account"/>

</set>

<property

name="email"

type="string"

update="false"

insert="true"

column="CUSTOMER_EMAIL"

length="82"

not-null="true"

/>

<property

name="passWord"

type="string"

update="false"

insert="true"

column="CUSTOMER_PASSWORD"

length="10"

not-null="true"

/>

<property

name="userId"

type="string"

update="false"

insert="true"

column="CUSTOMER_USERID"

length="12"

not-null="true"

unique="true"

/>

<property

name="firstName"

type="string"

update="false"

insert="true"

column="CUSTOMER_FIRSTNAME"

length="25"

not-null="true"

/>

<property

name="lastName"

type="string"

update="false"

insert="true"

column="CUSTOMER_LASTTNAME"

length="25"

not-null="true"

/>

</class>

</hibernate-mapping>

set name="accounts" 和一对多类标签指定了 Customer 和 Account 之间的关系。我还在 Account.hbm.xml 文件中定义了 Account 对象的映射。

CustomerDAOImpl.java 代表应用程序的 DAO,它在应用程序数据库中插入客户和帐户信息。CustomerDAOImpl 扩展了 Spring 的 HibernateDaoSupport,它用 Spring HibernateTemplate 简化了会话管理。这样,可以通过 getHibernateTemplate() 方法保存或检索数据。下面显示的 getCustomerAccountInfo() 对 Customer 进行 查找,通过 getHibernateTemplate().find 方法用 HQL 得到客户的帐户信息,如清单 4 所示。

清单 4. DAO 实现

public class CustomerDAOImpl extends HibernateDaoSupport

implements CustomerDAO{

public void addCustomer(Customer customer) {

getHibernateTemplate().save(customer);

// TODO Auto-generated method stub

}

public Customer getCustomerAccountInfo(Customer customer) {

Customer cust = null;

List list = getHibernateTemplate().find("from Customer customer " +

"where customer.userId = ?" ,

customer.getUserId(),Hibernate.STRING);

if(list.size() > 0){

cust = (Customer) list.get(0);

}

return cust;

}

所有这些都应当很容易掌握。现在来看代码的实际应用!

回页首

运行应用程序

要运行示例应用程序,必须首先 下载 Spring 框架 和它的全部依赖文件。接下来,释放框架到某一位置(比如 c:\ ),这会创建文件夹 C:\spring-framework-1.2-rc2(针对当前发行版)。在继续之前还必须下载和释放 Apache Ant 和 Cloudscape。下载 Cloudscape 之后,把它释放到 c:\ ,这会创建文件夹 C:\Cloudscape_10.0。

接下来,释放源代码到 c:\ ,这会创建 SpringProject2 文件夹。接下来修改 build.xml 文件的入口,用实际安装 Spring 的位置代替 C:\spring-framework-1.2-rc2,用实际安装 Cloudscape 的位置代替 C:\Program Files\IBM\Cloudscape_10.0。

打开命令行提示符,进入 SpringProject 目录,在命令行提示符下输入以下命令:build.

这会构建并运行 CreateBankCustomerClient 类,它会创建 Customer 类对象,用数据填充它,创建 Account 对象,填充它,并把它添加到 Customer 对象。

然后 CreateBankCustomerClient 会调用 CustomerDAOImpl.addCustomer 类,添加客户和帐户信息。一旦插入完成,CreateBankCustomerClient 会调用 CustomerDAOImpl.getCustomerAccountInfo 方法,根据 userid 得到客户和帐户信息。如果 CreateBankCustomerClient 执行成功,会在控制台上看到打印出 userid。也可以查询 Cloudscape 数据库检索客户和帐户信息。

回页首

结束语

在三部分的 Spring 系列 的第 2 部分中,我介绍了如何集成 Spring Hibernate 和 Spring AOP。结果是一个强健的持久性框架,支持声明性的实现事务。

在这个系列的下一篇,也是最后一篇文章中,我将介绍 Spring 的 MVC 模块,介绍如何用它来简化基于 Web 的应用程序的创建。

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有