《扩展 iBatis 以透明支持多种数据库.docx》由会员分享,可在线阅读,更多相关《扩展 iBatis 以透明支持多种数据库.docx(8页珍藏版)》请在第壹文秘上搜索。
1、扩展iBatis以透亮支持多种数据库iBatis是一个开源的对象关系映射框架,着重于POJO与SQL之间的映射关系。和其它ORM框架不同,iBatis开发者需要自己编写利维护SQL语句。为了得到更好的执行性能,在实际开发中免不了会使用一些数据库方言。随之而来的一个问题是,如何在增加对新的数据库支持的同时尽可能避开对已有应用程序代码的修改?本文供应了一个简洁有效的方法,通过扩展iBatis来透亮地支持多数据库方言。iBatis简介iBatis是一个开源的对象关系映射程序,着重于POJO与SQL之间的映射关系。使用时,开发者供应一个被称为SQL映射的XML文件,定义程序对象与SQL语句间的映射关系
2、,iBatis会依据SQL映射文件的定义,运行时自动完成SQL调用参数的绑定以及JDBCResuItSet到JaVaPoJO之间的转换。下面是一个简洁的例子,相比其它ORM工具,iBatis相对简洁,更简洁上手。清单1.POJO对象publicclassBIogDataimplementsSerializableprotectedStringid;protectedStringname;protectedintrating=0;publicStringgetld()returnid;1publicStringgetName()returnname;(publicintgetRating()re
3、turnrating;1publicvoidsetId(Stringid)this.id=id;)publicvoidsetName(Stringname)this.name=name;1publicvoidsetRating(intrating)this.rating=rating;清单2.SQL映射文件Sqlmarxmlinsertintoblogs(id,name,rating)values(#id#,#name#,#rating#)updateblogssetname=#name#,rating=#rating#whereid=#id#deletefromblogswhereid=#i
4、d#select*fromblogsorderbyratingdescfetchfirst$SiZe$rowsonly清单3.iBatis配置文件SQLMAPCONFIGXML/SQL映射声明清单4.SQL访问示例Stringcfg=,SQLMAPCONFIGXML;Readerr=Resources.getResourceAsReader(cfg);SqlMapClientclient=newSqlMapConfigParser().parse(r);/插入BlogDatao=newBlogData();o.setld(id,r);o.setName(test);client.insert(
5、SAVEBLOG,o);/更新o.setRating(10);Client.UpdateCUPDATEBLOG,o);/删除client.delete(REMOVEBLOG,id);/查询Mapparams=newHashMapO;params.put(size,5);Listl=client.queryForList(GETMOSTPOPULARBLOGparams,0,5);iBatis应用中的多数据库支持在iBatis应用中,开发者仍需自己编写详细的SQL语句,iBatis只是隐蔽和简化了JDBC的相关调用。实际开发中,我们不免需要就SQL语句针对各种特定的数据库进行特别优化,以期猎取更
6、好的执行性能,随之而来的一个问题是,如何应对新的数据库平台支持的需求。一般的做法是,修改SQL映射文件,供应一些新的针对新数据库平台的SQL语句版本,然后修改程序代码,添加相应调用。连续上面的例子。上面的例子中,对于SQL语句Getmostpopularblog的定义,我们使用了db2特有的sql方言“fetchfirstnROWS0NLY,对于这样的程序,假如盼望增加对MYSQL的支持,依据一般的做法,需要:1 .修改Sqlmarxml,增力口语句定义getmostpopularblog_mysql”。清单5.增加语句定义select*fromblogsorderbyratingdescfe
7、tchfirst$size$rowsonlyselect*fromblogsorderbyratingdesclimit0,$size$2 .搜寻程序代码,在每一个调用iBatis“GETMOSTPOPULARBLOG”的地方,增加检测MYSQL数据库引擎的代码,并添加对“GETMOSTPOPULARBLOG_MYSQL”的iBatis调用。清单6.增加检测数据库引擎的代码SqIMapClientclient=/查询Mapparams=newHashMapO;params.put(size,5);List1=null;Connectionconn=client.getCurrentConnec
8、tion();StringprodName=conn.getMetaData().getDatabaseProductName().toLowerCase();if(prodName.indexOf(mysql)-1)(/MicrosoftSQLServer1=client.queryForListCETMOSTPOPULARBLOG-MYSQL,params);)else1=client.queryForList(,GETMOSTPOPULARBLOG,params);每增加一个新的数据库支持,增加了一些新的针对新数据库平台的SQL语句版本,我们就不得不搜寻源代码,找出全部受到影响的iBat
9、is调用,修改并增加针对新数据库的特别调用。代码维护时,每次涉及使用数据库方言的SQL语句,我们也都必需记住当心谨慎地处理全部相关的数据库特化调用。这样的工作乏味且简洁出错。本文,我们试图在分析iBatis源码的基础上,通过适当扩展iBatis,供应一个高效便利的解决方案。扩展SqlMapConfigParser在iBatis应用中,SqlMapConfigParser负责解析iBatis配置文件,加载全部的SQL映射文件,生成SqIM叩Cliem实例,这是长久化调用的入口。SqIM叩COnfigParSer的实现并不简单。成员函数ParSer将传入的配置文件XML输入流交给一个XML解析器。
10、XML解析器解析XML输入,并针对每一个XMLFragmem调用合适的处理器处理。全部的处理器都在SqlMapConfigParser类实例初始化时预先被注册到XML解析器上,其中,对于iBatis配置中的SQL映射声明,只是简洁地调用类SqIM叩ParSer中的parser方法,解析并加载相应的SQL映射定义文件。清单7.SqlMapConfigParser实现publicclassSqIMapConfigParser/XML解析器protectedfinalNodeletParserparser=newNodeletParserO;publicSqlMapConfigParserO/注册X
11、ML处理器addSqlMapNodelets();/more(publicSqIMapClientparse(Readerreader)/调用XML解析器解析传入的配置文件XML输入流parser,parse(reader);returnvars.client;1protectedvoidaddSqlMapNodelets()/XML处理器,处理XPalhSqIMaPConfigsqlM叩”,即SQL映射声明parser.addNodelet(sqlMapConfigsqlMapnewNodelet()publicvoidprocess(Nodenode)throwsException(Pro
12、pertiesattributes=NodeletUtils.parseAttributes(node);Stringresource=attributes.getProperty(,resource);Readerreader=Resources.getResourceAsReader(resource);newSqlMapParser(vars).parse(reader);/调用SqlMapParseEparser方法/解析并加载SQL映射文件);我们继承iBatis原有的配置文件解析器实现SqlM叩COnfigParser,重写其中对SQL映射声明的处理。首先,我们重写SqIMapCo
13、nfigParser的成员函数addSq)MapNodelets对于从XML解析器传入的SQL映射声明节点,我们并不马上进行解析处理,而只是将它们纪录下来。清单8.重写addSqlMapNodclcts方法publicclassSqlMapConfigParserExextendsSq1MapConfigParser(ListSqlMapNodeList=newArrayList();protectedvoidaddSqlMapNodelets()/XML处理器,处理XPath:/SqIMaPCOnfigsqlMap”,即SQL映射声明parser.addNodelet(sqlMapConfi
14、gsqlMap,newNodelet()publicvoidprocess(Nodenode)throwsExceptionsqlMapNodeList.addNode(node););这些SQL映射声明被放到最终处理,此时SqlMapClient实例已经基本构造完毕,至少,我们可以平安地调用它的相关方法,打开数据库连接,查询数据库引擎相关信息。对于每个SQL映射声明,SqIMapConfigParSerEX调用其成员函数方法handleSqlMapNode进行相应的SQL映射文件解析和加载处理,数据库引擎支持的SQL方言版本信息作为参数被一并传入。清单9.重写parse方法publicint
15、erfaceDialectMapping(publicStringgetDialect(StringproductName);/返回数据库平台支持的SQL方言信息)publicclassSqlMapConfigParserExextendsSqlMapConfigParser(ListSqlMapNodeList=newArrayList();DiaIectMappingdialectMapping=publicSqIMapClientparse(Readerreader)super,parse(reader);StringSqlDialect=null;SqIMapCIientclient=vars.client;Connectionconn=client.getDataSource().getConnection();DatabaseMetaDatadbMetaData=conn.getMetaData();StringproductName=dbMetaData.getDatabaseProductName();SqlDialect=dialectMapp