java

位置:IT落伍者 >> java >> 浏览文章

在Spring中使用JDO


发布日期:2018年02月13日
 
在Spring中使用JDO

前言

在此前的Spring A Developers Notebook摘录中作者Bruce Tate和Justin Gehtland讨论了在Spring中使用iBATIS OR持久化框架的内容出于其他的原因此选择要求深入SQL底层在这篇第五章的摘录中他们转向那些更加彻底地把SQL从你的Spring应用中独立的持久化框架

JDO是基于接口标准的持久化或如Tate 和Gehtland所言在Java应用中非EJB标准的持久化一经提及JDO他们不是卷入那场众说纷纭的辩论之中而是着眼于如何把一顶级的实现Kodo引入到你的Spring应用中接着转去讨论最流行的且可能是与Spring集成最好的OR框架Hibernate正如他们所指出的尽管是非标准的但你可以说在EJB之后Hibernate是世界上最流行的持久化框架了本章中作者们不仅为你演示设置每个框架的具体细节而且还清晰地表明了各种框架的使用方法之差异

就象Developers Notebook 系列中所有的书一样你将由直接的且实用的方式获得信息这些信息包含了完成你工作所需的细节换言之一切来自实战没有讲义

在Spring中使用JDO

JDO是Java 应用中非EJB标准的一种持久化方式在这部分中我们将使用我们喜欢的JDO实现Kodo来实现我们应用中的透明持久化虽然我们不会试着教给你JDO的知识但会说明怎样使用JDO来为我们的应用提供持久化的功能

无论你从事JDO多长时间可能都会使你想起众说纷纭的辩论直到最近大多数人都避免使用JDO随着JDO 版本和许多可靠的商业化及开源的JDO实现的暂停发布这个持久化标准看起来就象是一个强壮的运动员在ORM舞台上蓄势待发(译注在翻译本文时获悉JDO已投票通过)实际上我所钟爱的ORM是Solar Metric的Kodo 它或许称得上JDO实现中的矫矫者了当Kodo达到商业化实现时它看起来比其它可供选择的实现更加强壮且已获得更灵活的映射支持更易于管理来自持久化企业核心越来越丰富的支持考虑以下这些优势? 若你正寻找某些免费的或能对源代码更好地控制的JDO实现你可在众多的开源的JDO实现中选择? 你可选择一价格合理的商业化产品而且能得到支持和维护? 若选择了那些一流的商业化厂商从较佳管理到灵活映射你都可能得到难以置信的功能和性能? 在获得所有的这些优势的同时你还能获得开源标准提供的保护和安全

我该怎么办?

你将使用JDO来创建一个持久化模型随后在fa?ade层中使用那个模型尽管应用程序中已创建了业务域模型但仍未被持久化你业已获得fa?ade层的接口那么只需完成下述的操作步骤便可在你的应用中使用JDO了通过字节码增强器(byte code enhancer)让域模型持久化

简单修改Spring的配置文件你就可在你的应用中使用Kodo 通过JDO模板建构使用持久化模型的fa?ade

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

首先你需要下载和安装Kodo从试用的版本开始你可在这里找到本书中使用版本再次提醒你得把/kodojdo/lib中的包放入我们的/lib目录下

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

示例

你也需要在Ant 建构文件中给kodojdojar jdojar and Jakartacommonslangjar增加路径元素

下一步建构持久化映射最简便的办法就是通过Kodo向导运行Workbench(在你所安装的Kodo的\bin目录下)并从菜单中选择MetaDataàCreate MetaDate反之你可使用/kodojdo/bin目录下的metadatatool 和mappingtool两个脚本它们分别被taMappingTool和taJDOMetaDataTool的运行文件所使用

为了与其它JDO版本保持一致因此你打算用XML从头建构映射文件用类的元数据和mapping 文件生成jdo文件此两文件都在/war/WEBINF/classes/com/springbook目录下

示例声明元数据文件

示例 packagejdo

示例描述了映射文件

示例 packagemapping

几乎太容易了模型本身没有被持久化那就是我们使用OR技术的原因尽管你仍需在你的应用程序中有一层代码也就是我们所说的fa?ade层来调用那个持久化模型因此你将看到一系列的模板调用查询器(finder)声明了JDO查询语句及持久化删除更新新增的对象你已经有了一个接口但还需要实现fa?ade(如示例

示例 KodoRentABikejava

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

public class KodoRentABike extends JdoDaoSupport implements RentABike {private String storeNamepublic List getBikes( ) {return (List)getJdoTemplate( )find(Bikeclass)}public Bike getBike(String serialNo) {Collection c = getJdoTemplate( )find(Bikeclass serialNo == + serialNo + Bike b = nullif(csize( ) > ) {b = (Bike)erator()next( )}return b}public Bike getBike(int bikeId) {return (Bike)getJdoTemplate( )getObjectById(Bikeclass new Long(bikeId))}public void saveBike(Bike bike) {getJdoTemplate( )makePersistent(bike)}public void deleteBike(Bike bike) {getJdoTemplate( )deletePersistent(bike)}//etc

最后你需要设定一些配置来把这些都组装在一起示例先说明了JDO的配置

示例 packageproperties

# To evaluate or purchase a license key visit YOUR_LICENSE_KEY_HEREjavaxjdoPersistenceManagerFactoryClass kodojdbcruntimeJDBCPersistenceManagerFactoryjavaxjdooptionConnectionDriverName commysqljdbcDriverjavaxjdooptionConnectionUserName bikestorejavaxjdooptionConnectionPasswordjavaxjdooptionConnectionURL jdbcmysql://localhost/bikestorejavaxjdooptionOptimistic truejavaxjdooptionRetainValues truejavaxjdooptionNontransactionalRead truejavaxjdooptionRestoreValues truekodoLog DefaultLevel=WARN Runtime=INFO Tool=INFOkodoPersistenceManagerImpl DetachOnClose=true注意DetachOnClose 选项它确保了JDO在关闭连接时的延迟加载因而你应用程序的其它部分 象视图(view)只能访问已加载的BeanSpring上下文需把JDO持久化管理器持久化管理工厂fa?ade以及任何在fa?ade上的服务组合在一起这些都在context中完成(示例Example RentABikeAppservletxml E\RentABikeApp\war\WEBINF\kodopropertiesBruces 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 目录中复制hibernatejar aopalliancejar cgligfulljar domjjar ehcachejar 及admgjar到你项目的/lib目录下

由于Hibernate使用了反射机制 因此就没有字节加强步骤所有你已尝试过让模型持久化的做法就是来创建映射并且在上下文中引用他们示例表明了创建映射的过程

Example Bikehbmxml

unsavedvalue=>

Hibernate版的这个映射较之JDO版的相应代码更为雅致它有着更加丰富的识别码(Identification)生成库

Example Customerhbmxml

unsavedvalue=> Example Reservationhbmxml unsavedvalue=>cascade=none/>cascade=none/>

在上下文中你需要配置Hibernate属性配置session factory 并把session factory插入到fa?ade中使用JDO 上下文iBATIS上下文及Hibernate上下文的事务策略都是一样的就想他们本该那样似的那就是依赖注入正为你所做的一部分示例表明了对上下文的变动

Example RentABikeAppservletxml

Bruces Bikesclass=orgspringframeworkormhibernateLocalSessionFactoryBean>

com/springbook/Bikehbmxmlcom/springbook/Customerhbmxmlcom/

springbook/ReservationhbmxmlnetsfhibernatedialectMySQLDialecttrue

不象JDO那样Hibernate用户经常把所有的映射类放入独立定的多个文件中这不是必需的仅是Hibernate用户特别喜欢管理事前的一种方式而已

既然已有了一个fa?ade接口你只需一个Hibernate实现即可你可以使用模板就象JDO那样至于查询器(Finder)你所要做的就是指定一个Hibernate 查询语言(HQL)语句至于更新(update)部分你所要做的就是指明将被存储的新对象示例就是个非常薄的fa?ade的例子

Example HibRentABikejava

package comspringbookimport orgspringframeworkormhibernatesupportHibernateDaoSupportimport javautilListimport javautilDateimport javautilSetimport netsfhibernateQuerypublic class HibRentABike extends HibernateDaoSupport implements RentABike {private String namepublic List getBikes( ) {return getHibernateTemplate( )find(from Bike}public Bike getBike(String serialNo) {Bike b = nullList bikes = getHibernateTemplate( )find(from Bike where serialNo = ? serialNo)if(bikessize( ) > ) {b = (Bike)bikesget(}return b}public Bike getBike(int bikeId) {return (Bike)getHibernateTemplate( )load(Bikeclass new Integer(bikeId))}public void saveBike(Bike bike) {getHibernateTemplate( )saveOrUpdate(bike)}public void deleteBike(Bike bike) {getHibernateTemplate( )delete(bike)}public void setStoreName(String name) {thisname = name}public String getStoreName( ) {return thisname}public List getCustomers( ) {return getHibernateTemplate( )find(from Customer}public Customer getCustomer(int custId) {return (Customer)getHibernateTemplate( )load(Customerclass new Integer(custId))}public List getReservations( ) {return getHibernateTemplate( )find(from Reservation}public List getReservations(Customer customer) {return getHibernateTemplate( )find(from Reservation where custId = ? customergetCustId( ))}public List getReservations(Bike bike) {return getHibernateTemplate( )find(from Reservation where bikeId = ? bikegetBikeId( ))}public List getReservations(Date date) {return getHibernateTemplate( )find(from Reservation where resdate = ? date)}public Reservation getReservation(int resId) {return (Reservation)getHibernateTemplate( )load(Reservationclass new Integer(resId))}}发生了什么事?Hiberante的做法与JDO极其相似Spring的JDO模板代表着一套默认的DAO方法你所要做的就是来定制他们通常是HQL查询语句及任何HQL参数化查询中参数的可能取值接着Spring拿到控制权获得session发动查询并且处理任何的异常再次重申你看到独特的平衡示例给了在不使用Spring时你不得不编写的典型的Hibernate之方法Example HibRentABikejava public List getBikesOldWay( ) throws Exception {// Relies on other static code for configuration// and generation of SessionFactory Might look like:// Configuration config = new Configuration( )// configaddClass(Bikeclass)addClass(Customerclass)// addClass(Reservationclass)// SessionFactory mySessionFactory = Configuration// buildSessionFactory( )List bikes = nullSession s = nulltry {s = mySessionFactoryopenSession( )bikes = sfind(from Bike}catch (Exception ex) {//handle exception gracefully}finally {sclose( )}return bikes}示例再次表明了在Spring中实现查找的相应代码Example HibRentABikejava 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的应用程序中添加的服务的相关知识

作者czyczy(作者的blog

上一篇:技术分析:使用Eclipse进行SWT编程(图)

下一篇:Java中集合容器类List和Set的用法