快捷搜索:  www.ymwears.cn

在Spring中使用JDO

在此前的Spring: A Developer's Notebook摘录中,作者Bruce Tate和Justin Gehtland评论争论了在Spring中应用iBATIS OR持久化框架的内容。出于其他的缘故原由,此选摘要求深入SQL底层。在这篇第五章的摘录中,他们转向那些加倍彻底地把SQL从你的Spring利用中自力的持久化框架。

JDO是基于接口标准的持久化,或如Tate 和Gehtland所言,“在Java利用中非EJB标准的持久化”。一经说起JDO,他们不是卷入那场“众说纷纭”的辩论之中,而是着眼于若何把一顶级的实现,Kodo,引入到你的Spring利用中。接着转去评论争论最盛行的,且可能是与Spring集成最好的OR框架:Hibernate。正如他们所指出的,“只管长短标准的,但你可以说在EJB之后,Hibernate是天下上最盛行的持久化框架了。”本章中,作者们不仅为你演示设置每个框架的详细细节,而且还清晰地注解了各类框架的应用措施之差异。

就象Developer's Notebook 系列中所有的书一样,你将由直接的且实用的要领得到信息,这些信息包孕了完成你事情所需的细节。换言之:“统统来自实战,没有教材。”

版权声明:任何得到Matrix授权的网站,转载时请务必保留以下作者信息和链接

作者:czyczy(作者的blog:http://blog.matrix.org.cn/page/czyczy)

原文:http://www.matrix.org.cn/resource/article/44/44313_Spring+JDO.html

关键字:Spring;JDO

在Spring中应用JDO

JDO是Java 利用中非EJB标准的一种持久化要领。在这部分中,我们将应用我们爱好的JDO实现,Kodo,来实现我们利用中的透明持久化。虽然我们不会试着教给你JDO的常识,但会阐明如何应用JDO来为我们的利用供给持久化的功能。

无论你从事JDO多长光阴,可能都邑使你想起众说纷纭的辩论。直到近来,大年夜多半人都避免应用JDO。跟着JDO2.0 版本和许多靠得住的商业化及开源的JDO实现的停息宣布,这个持久化标准看起来就象是一个强壮的运动员在ORM舞台上蓄势待发(译注:在翻译本文时获悉,JDO2.0已投票经由过程)。实际上,我所钟爱的ORM是Solar Metric的Kodo, 它或许称得上JDO实现中的矫矫者了。当Kodo达到商业化实现时,它看起来比其它可供选择的实现加倍强壮,且已得到更机动的映射支持、更易于治理,来矜持久化企业核心越来越富厚的支持,斟酌以下这些上风:

若你正探求某些免费的或能对源代码更好地节制的JDO实现,你可在浩繁的开源的JDO实现中选择。

你可选择一价格合理的商业化产品,而且能获得支持和掩护。

若选择了那些一流的商业化厂商,从较佳治理到机动映射,你都可能获得难以置信的功能和机能。

在得到所有的这些上风的同时,你还能得到开源标准供给的保护和安然。

我该怎么办?

你将应用JDO来创建一个持久化模型,随后在façade层中应用那个模型。只管利用法度榜样中已创建了营业域模型,但仍未被持久化。你业已得到façade层的接口,那么只需完成下述的操作步骤,便可在你的利用中应用JDO了:

1.经由过程字节码增强器(byte code enhancer)让域模型持久化。

2.简单改动Spring的设置设置设备摆设摆设文件,你就可在你的利用中应用Kodo。

3.经由过程JDO模板,建构应用持久化模型的façade。

就这些了。Spring会治来由PersistenceManagerFactory和PersistenceManager组成的JDO之核心资本。把这些特殊的选项算作是JDO的数据源与连接。你还可以让Spring来治理事务。上述三个步骤便是你所要完成的事情。

首先,你必要下载和安装Kodo。从试用的版本开始,你可在这里找到http://www.solarmetric.com。本书中应用3.2.1版本。再次提醒,你得把/kodo-jdo-3.2.1/lib中的包放入我们的/lib目录下。

为持久化模型,你得改动Ant义务以添加JDO字节码增强的步骤:象示例5-8所示的那样,添加Ant义务来完成这一动作。

示例5-8.

你也必要在Ant 建构文件中给kodo-jdo.jar, jdo-1.0.1.jar, and Jakarta-commons-lang-1.0.1.jar增添路径元素。

下一步,建构持久化映射。最简便的法子便是经由过程Kodo领导。运行Workbench(在你所安装的Kodo的in目录下),并从菜单中选择MetaDataàCreate MetaDate。反之,你可应用/kodo-jdo-3.2.1/bin目录下的metadatatool 和mappingtool两个脚本,它们分手被kodo.jdbc.meta.MappingTo-ol和kodo.meta.JDOMetaDataTool的运行文件所应用。

为了与其它JDO版本维持同等,是以你盘算用XML从头建构映射文件。用类的元数据和.mapping 文件天生.jdo文件。此两文件都在/war/WEB-INF/classes/com/springbook目录下。

示例5-9声明元数据文件。

示例5-9package.jdo

示例5-10描述了映射文件。

示例5-10. package.mapping

险些太轻易了。模型本身没有被持久化,那便是我们应用OR技巧的缘故原由。只管你仍需在你的利用法度榜样中有一层代码,也便是我们所说的façade层,来调用那个持久化模型。是以你将看到一系列的模板调用。查询器(finder)声清楚明了JDO查询语句,及持久化删除、更新、新增的工具。你已经有了一个接口,但还必要实现façade(如示例5-11)。

示例 5-11. KodoRentABike.java

这不是完全的JDO查询说话的查询;它只不过是个过滤器而已。JDO 2.0将会增添一个便利的查询字符串,因而你可以以单一的字符串来添加完全的JDO查询,而毋须建构完全的查询。

public class KodoRentABike extends JdoDaoSupport implements RentABike {

private String storeName;

public List getBikes( ) {

return (List)getJdoTemplate( ).find(Bike.class);

}

public Bike getBike(String serialNo) {

Collection c = getJdoTemplate( ).find(Bike.class, "serialNo == '" + serialNo + "'");

Bike b = null;

if(c.size( ) > 0) {

b = (Bike)c.iterator().next( );

}

return b;

}

public Bike getBike(int bikeId) {

return (Bike)getJdoTemplate( ).getObjectById(Bike.class, new Long(bikeId));

}

public void saveBike(Bike bike) {

getJdoTemplate( ).makePersistent(bike);

}

public void deleteBike(Bike bike) {

getJdoTemplate( ).deletePersistent(bike);

}

//etc.

着末,你必要设定一些设置设置设备摆设摆设来把这些都组装在一路。示例5-12先阐清楚明了JDO的设置设置设备摆设摆设。

示例 5-12. package.properties

# To evaluate or purchase a license key, visit http://www.solarmetric.com

kodo.LicenseKey: YOUR_LICENSE_KEY_HERE

javax.jdo.PersistenceManagerFactoryClass: kodo.jdbc.runtime.

JDBCPersistenceManagerFactory

javax.jdo.option.ConnectionDriverName: com.mysql.jdbc.Driver

javax.jdo.option.ConnectionUserName: bikestore

javax.jdo.option.ConnectionPassword:

javax.jdo.option.ConnectionURL: jdbc:mysql://localhost/bikestore

javax.jdo.option.Optimistic: true

javax.jdo.option.RetainValues: true

javax.jdo.option.NontransactionalRead: true

javax.jdo.option.RestoreValues: true

kodo.Log: DefaultLevel=WARN, Runtime=INFO, Tool=INFO

kodo.PersistenceManagerImpl: DetachOnClose=true

留意DetachOnClose 选项。它确保了JDO在关闭连接时的延迟加载,因而你利用法度榜样的其它部分 ,象视图(view),只能造访已加载的Bean。

Spring高低文需把JDO持久化治理器,持久化治理工厂,façade,以及任何在façade上的办事组合在一路。这些都在context中完成(示例5-13)。

Example 5-13. RentABikeApp-servlet.xml

E:RentABikeAppwarWEB-INFkodo.properties

Bruce's Bikes

记得你已经有了一个应用façade的测试用例,是以你可以建构并让它运行起来。

发生了什么事?

这是个展示Spring功能的异常好的例子。只管你已从根本上颠覆了持久化层的实现,但这并没有影响到利用法度榜样的其它部分。以下便是它如何事情的阐明。

Spring首先应用依附注入来办理所有的依附。加载的高低文设置设置设备摆设摆设了含有你所供给数据源的JDO,随之在façade的JDO实现中设定持久化治理器工厂。接着,当你在façade上调用措施时,Spring给了你持久化治理器并应用它来处置惩罚你所供给的查询。你可以这样来看:Spring供给一通俗的(generic)JDO

façade措施,称之为模板。你插入(plug in)细节,并把节制权交给Spring。

当你在骑自行车或编写代码时,一个最紧张的衡量标准是效率。每当脚踏板转一圈,或每写一行代码,你可完成若干的事情?想想JDO版本的利用法度榜样,Spring编程模型最迫切的事是效率。为了看明白我说的意思,想一下你没见到的:

没有非常治理,而每每便是这些非常治理纷乱了你利用法度榜样的较底层。使用Spring未捕捉非常(Unchecked Exception)的机制,你可以在获得非常的地方适当地做些工作。

没有资本治理。只要有JDBC连接的地方,就有JDO持久化的治理器。Spring设置设置设备摆设摆设了持久化治理器工厂,并且在模板内为你治理持久化治理器。

你没有被强制治理事务及facade的安然。Spring让你很轻易地来设置设置设备摆设摆设这些器械,是以你可以从你的façade层中将丑陋的细节束之高阁,让它专注于应用持久化模型。

在Spring的模板中这些都为你完成了,这些模板放在与Spring框架一路的代码中,这些让你读起来加倍轻易理解,或在需要时debug之。简而言之,你可以在每一行的代码中获得平衡,更象你在高速地踏自行车。那便是所有最成功的框架和法度榜样设计说话的底线。

在Spring中应用Hibernate

Spring开拓职员选择Hibernate作为持久化框架已经有很长的一段光阴了。只管Spring团队在持续致力于改良与其它持久化框架的集成,但在所有与Spring集成的持久化框架中, Hibermate维持了最为广泛应用的职位地方。确切地说,这两个轻量级的办理规划在互相匆匆进中得到成功,他们一路茁壮生长。在这此例中,我们将注解若何将Spring与Hibernate集成起来一同事情。

Hibernate是个优秀的持久化框架。她深受迎接,运行速率相称快,并且是免费的。除此之外,它还拥有富厚的映射支持,且是一个便利的应用模型,使得它在举世的开拓者中盛行起来。Hibernate已经在小型和中型的项目中经受住了异常好的磨练。实际上,只管它还未被确觉得标准,但可以说在EJB之后,Hibernate是天下上最盛行的持久化框架。

我该怎么办?

既然你已用持久化域模型和façade 的ORM设置设置设备摆设摆设了Spring,你就懂得了基础的流程。因为Spring 被设计成与Hibernate 自力,你只需从Spring的/dist 目录中复制hibernate2.jar, aopalliance.jar, cglig-full-2.0.2.jar, dom4j.jar, ehcache-1.1.jar, 及admg.jar到你项目的/lib目录下。

因为Hibernate应用了反射机制, 是以就没有字节加强步骤。所有你已考试测验过让模型持久化的做法,便是来创建映射,并且在高低文中引用他们。示例5-14,5-15及5-16注解了创建映射的历程。

Example 5-14. Bike.hbm.xml

Hibernate版的这个映射较之JDO版的响应代码更为高雅。它有着加倍富厚的识别码(Identification)天生库。

Example 5-15. Customer.hbm.xml

Example 5-16. Reservation.hbm.xml

在高低文中,你必要设置设置设备摆设摆设Hibernate属性,设置设置设备摆设摆设session factory, 并把session factory插入到façade中。应用JDO 高低文、iBATIS高低文及Hibernate高低文的事务策略都是一样的,就想他们本该那样似的。那便是依附注入正为你所做的一部分。示例5-17注解了对高低文的更改。

Example 5-17. RentABikeApp-servlet.xml

Bruce's Bikes

com/springbook/Bike.hbm.xml

com/springbook/Customer.hbm.xml

com/springbook/Reservation.hbm.xml

net.sf.hibernate.dialect.MySQLDialect

true

不象JDO那样,Hibernate用户常常把所有的映射类放入自力定的多个文件中。这不是必需的,仅是Hibernate用户分外爱好治理事前的一种要领而已。

既然已有了一个façade接口,你只需一个Hibernate实现即可。你可以应用模板,就象JDO那样。至于查询器(Finder),你所要做的便是指定一个Hibernate 查询说话(HQL)语句。至于更新(update)部分,你所要做的便是指明将被存储的新工具。示例5-18便是个异常薄的façade的例子。

Example 5-18. HibRentABike.java

package com.springbook;

import org.springframework.orm.hibernate.support.HibernateDaoSupport;

import java.util.List;

import java.util.Date;

import java.util.Set;

import net.sf.hibernate.Query;

public class HibRentABike extends HibernateDaoSupport implements RentABike {

private String name;

public List getBikes( ) {

return getHibernateTemplate( ).find("from Bike");

}

public Bike getBike(String serialNo) {

Bike b = null;

List bikes = getHibernateTemplate( ).

find("from Bike where serialNo = ?", serialNo);

if(bikes.size( ) > 0) {

b = (Bike)bikes.get(0);

}

return b;

}

public Bike getBike(int bikeId) {

return (Bike)getHibernateTemplate( ).

load(Bike.class, new Integer(bikeId));

}

public void saveBike(Bike bike) {

getHibernateTemplate( ).saveOrUpdate(bike);

}

public void deleteBike(Bike bike) {

getHibernateTemplate( ).delete(bike);

}

public void setStoreName(String name) {

this.name = name;

}

public String getStoreName( ) {

return this.name;

}

public List getCustomers( ) {

return getHibernateTemplate( ).find("from Customer");

}

public Customer getCustomer(int custId) {

return (Customer)getHibernateTemplate( ).

load(Customer.class, new Integer(custId));

}

public List getReservations( ) {

return getHibernateTemplate( ).find("from Reservation");

}

public List getReservations(Customer customer) {

return getHibernateTemplate( ).

find("from Reservation where custId = ?", customer.getCustId( ));

}

public List getReservations(Bike bike) {

return getHibernateTemplate( ).

find("from Reservation where bikeId = ?", bike.getBikeId( ));

}

public List getReservations(Date date) {

return getHibernateTemplate( ).

find("from Reservation where resdate = ?", date);

}

public Reservation getReservation(int resId) {

return (Reservation)getHibernateTemplate( ).

load(Reservation.class, new Integer(resId));

}

}

发生了什么事?

Hiberante的做法与JDO极其相似。Spring的JDO模板代表着一套默认的DAO措施。你所要做的便是来定制他们,平日是HQL查询语句,及任何HQL参数化查询中参数的可能取值。接着Spring拿到节制权,得到session,发动查询并且处置惩罚任何的非常。

再次重申,你看到独特的平衡。示例5-19给了在不应用Spring时,你不得不编写的范例的Hibernate之措施。

Example 5-19. HibRentABike.java

public List getBikesOldWay( ) throws Exception {

// Relies on other static code for configuration

// and generation of SessionFactory. Might look like:

// Configuration config = new Configuration( );

// config.addClass(Bike.class).addClass(Customer.class).

// addClass(Reservation.class);

// SessionFactory mySessionFactory = Configuration.

// buildSessionFactory( );

List bikes = null;

Session s = null;

try {

s = mySessionFactory.openSession( );

bikes = s.find("from Bike");

}catch (Exception ex) {

//handle exception gracefully

}finally {

s.close( );

}

return bikes;

}

示例5-20再次注解了在Spring中实现查找的响应代码。

Example 5-20. HibRentABike.java

public List getBikes( ) {

return getHibernateTemplate( ).find("from Bike");

}

新手必要分外留意本文代码中的黑体字部分,利用法度榜样的每一代码块必须尽力完成好一个功能,且只能一个。

关于…

…Hibernate的替代品?Hibernate确凿是免费的、运行速率快的、有效且是盛行的。它已经受住了磨练,且有着极其优秀的机能和机动性。大年夜部分的对象中有着很好的Hibernate支持,并且Hibernate支持所有相关的数据库。但我仍只保举在小型和大年夜型的利用中应用Hibernate。

到今朝为止,H作为一开源框架,持久化社区不能过多地赞扬Hibernate或声讨其替代者。如斯盲目的拥趸导致了礼教崇拜式的决策。Hibernate的竞争者们在某些方面比她做得更好。若你的利用法度榜样有以下的特性,不妨试一试其他的办理规划:

标准

JDO和JDBC办理规划已然成为标准。只管Hibernate是开源的,但她还未被确觉得标准。在以前的十年中,你得信赖JBoss 组织和基金会的念头来做精确的工作,且对任何的框架而言,至今已证实那是弗成靠的职位地方。

治理

其他的办理规划易于治理,如Kodo JDO和Top Link就有治理面板,用他们很轻易地来监控缓存状态,及主动(eager)加载或延迟加载的状态。

映射

其他的框架有着功能更强大年夜的和加倍机动的映射支持。若你不想对你的数据库schema进行节制,你最好选用其他的办理规划。你可能也爱好用GUI对象来映射你的schema ,那么,象JDO Genie 或Cayenne可能就最得当你的利用。

总而言之,应用主流的框架或许终极可能是精确的选择,但平日环境下,只要轻细深入的商量,你就可以找到加倍相宜的办理规划。Hibernate确凿值得斟酌,但别忘了还有其他好的选择。

运行一个测试用例

运行测试用例是很轻易的事,你已经学会了。它便是你在façade 上运行的那个测试用例。

我该怎么办?

因为测试用例已存在,是以你可以运行现有的façade测试。你仅要确保精确设置测试数据即可。且你可以应用未被变化过的利用高低文。那便是Spring的强大年夜之处,可测试性。

发生了什么事?

你应用过已存在的测试用例,这很好,由于你只必要治理数据库增长的细节,鄙人章中,你将开始深入进修可在Spring AOP的利用法度榜样中添加的办事的相关常识。

您可能还会对下面的文章感兴趣: