|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
专门做了这个例子;而java的这个例子好像就是为了教学而写的,很多教学目的的例子是不考虑优化、性能的。xml|数据|数据库先容
办理把XML无效的、主动的转换收支干系数据库的成绩有各类体例。数据库厂商好比IBM、Microsoft、Oracle和Sybase已开辟了转换XML到数据库表中的帮助工具。各类办理计划以下。
OracleXMLSQLUtility把XML文档元素建模为一组嵌套的表。经由过程利用Oracle对象数据范例建模套进的元素。"SQL-to-XML"转换利用被对象数据范例援用的表,和嵌套的元素之间的一到一联系关系来机关XML文档。"XML-to-SQL"大概请求数据模子的改善(从干系转换到对象-干系)或从头机关最后的XML文档。
IBMDB2XMLExtender同意存储XML文档为BLOB式的对象或分化到一组表中。后者得变更叫做XML搜集,以XML1.0语法界说。
Microsoft经由过程扩大SQL-92并参与OPENXML行集来办理成绩。
SybaseAdaptiveServer参与ResultSetXmlJava类作为在两个偏向上处置XML文档的基本。
在这篇文章中,我们将具体会商这些厂商的办理计划。今后,我们将实验回覆以下成绩:
我们能够调剂并简化成绩吗?
在异构数据库情况中准确的路子是甚么?
我将利用以下辞汇表作为一个例子。
<!--复杂范例-->
<!ELEMENTCURRENCY1(#PCDATA)>
<!ATTLISTCURRENCY1e-dtypeNMTOKEN#FIXED"string"
e-dsizeNMTOKEN#FIXED"3">
<!ELEMENTCURRENCY2(#PCDATA)>
<!ATTLISTCURRENCY2e-dtypeNMTOKEN#FIXED"string"
e-dsizeNMTOKEN#FIXED"3">
<!ELEMENTAMOUNT(#PCDATA)>
<!ATTLISTAMOUNTe-dtypeNMTOKEN#FIXED"decimal">
<!ELEMENTSETTLEMENT(#PCDATA)>
<!ATTLISTSETTLEMENTe-dtypeNMTOKEN#FIXED"date">
<!ELEMENTBANKCODE(#PCDATA)>
<!ATTLISTBANKCODEe-dtypeNMTOKEN#FIXED"string">
<!ELEMENTBANKACCT(#PCDATA)>
<!ATTLISTBANKACCTe-dtypeNMTOKEN#FIXED"string">
<!--派生范例-->
<!ELEMENTACCOUNT(BANKCODE,BANKACCT)>
<!ELEMENTFXTRADE(CURRENCY1,CURRENCY2,AMOUNT,SETTLEMENT,ACCOUNT)>
OracleXML-SQLUtility(XSU)
SQL到XML的映照
Oracle把对象援用链从数据库转换到XML文档的条理布局中。在对象-干系数据库,在表FXTRADE中的字段ACCOUNT被建模为范例AccountType的一个对象援用:
CREATETABLEFXTRADE
{
CURRENCY1CHAR(3),
CURRENCY2CHAR(3),
AMOUNTNUMERIC(18,2),
SETTLEMENTDATE,
ACCOUNTAccountType//对象援用
}
CREATETYPEAccountTypeasOBJECT
{
BANKCODEVARCHAR(100),
BANKACCTVARCHAR(100)
}
从给定的对象-干系模子天生响应的XML文档(利用"SELECT*FROMFXTRADE")以下
<?xmlversion="1.0"?>
<ROWSET>
<ROWnum="1">
<CURRENCY1>GBP</CURRENCY1>
<CURRENCY2>JPY</CURRENCY2>
<AMOUNT>10000</AMOUNT>
<SETTLEMENT>20010325</SETTLEMENT>
<ACCOUNT>
<BANKCODE>812</BANKCODE>
<BANKACCT>00365888</BANKACCT>
</ACCOUNT>
</ROW>
<!--additionalrows...-->
</ROWSET>
从数据库提取XML
上面的例子取自Oracle的XSU文档,带有SQL语句的得当交换并利用Oracle的纯JavaJDBC薄驱动程序。
起首,创建了OracleXMLQuery的一个实例,厥后,实行一个查询,并把了局暗示为下面的XML文档的情势。相似的,能够提取XML文档到DOM的情势;在这类情形下,能够挪用qry.getXMLDOM()代替getXMLString()。
importoracle.jdbc.driver.*;
importoracle.xml.sql.query.OracleXMLQuery;
importjava.lang.*;
importjava.sql.*;
//测试XML文档天生为String的类
classtestXMLSQL{
publicstaticvoidmain(String[]args)
{
try{
//创建毗连
Connectionconn=getConnection("scott","tiger");
//创建查询类
OracleXMLQueryqry=newOracleXMLQuery(conn,
"SELECT*FROMFXTRADE");
//失掉XML字符串
Stringstr=qry.getXMLString();
//打印XML输入
System.out.println("TheXMLoutputis:
"+str);
//老是封闭查询来开释一切资本
qry.close();
}catch(SQLExceptione){
System.out.println(e.toString());
}
}
//失掉给定的用户名字和口令的毗连
privatestaticConnectiongetConnection(Stringusername,
Stringpassword)
throwsSQLException
{
//注册JDBC驱动程序
DriverManager.registerDriver(new
oracle.jdbc.driver.OracleDriver());
//创建OCI8驱动程序的毗连
Connectionconn=
DriverManager.getConnection(
"jdbc:oracle:thin:@dlsun489:1521:ORCL",
username,password);
returnconn;
}
}
存储XML在数据库中
在例子中利用OracleXMLSave来存储我们的XML文档到对象干系模子中;insertXML办法举行实践的数据拔出。
importjava.sql.*;
importoracle.xml.sql.dml.OracleXMLSave;
publicclasstestXMLInsert
{
publicstaticvoidmain(Stringargs[])
throwsSQLException
{
Connectionconn=getConnection("scott","tiger");
OracleXMLSavesav=newOracleXMLSave(conn,"scott.FXTRADE");
//Assumethattheuserpassesinthisdocumentas0-arg
sav.insertXML(args[0]);
sav.close();
}
...
}
假如XML和在数据库中的对象-干系模子是同步的则统统一般,可是假如分歧呢?在这类情形下你有两种选择。
调剂对象-干系模子--能够机关一个可修正的对象-干系视图来完成多表修正;大概,作为替换,利用XSLT,能够把XML文档分化成一组"平展的"子文档。XSU不同意属性值的存储;它倡议你把属性转换成元素。
OracleXSU的总结
经由过程以下对象-干系模子机关划定规矩建模XML到SQL映照:把每一个嵌套的XML元素映照在得当的范例的一个对象援用上。映照划定规矩被暗含的嵌进到数据库模子中。
JavaAPI由类OracleXMLQuery和OracleXMLSave构成。
IBMDB2XMLExtender
SQL到XML的映照
IBM的XMLExtender为利用DB2作为XML堆栈供应两种会见和存储办法:
XML列:存储和取回全部XML文档为DB2列数据
XML搜集:把XML文档分化成一组干系表,或从一组干系表分解XML文档。
DTD存储在DTD堆栈中,叫做DTD_REF的一个DB2表中;它的形式名字是"db2xml"。在DTD_REF表中每一个DTD都有一个独一的ID。在数据库表和XML文档的布局之间的映照是经由过程数据会见界说(DAD)文件的体例来界说的。DAD援用一个处置过的文档DTD,从而供应在XML文档、它的DTD和在数据库表之上的映照划定规矩之间的桥梁。
上面是一个例子DAD。
<?xmlversion="1.0"?>
<!DOCTYPEDADSYSTEM"dad.dtd">
<DAD>
<dtdid>FXTRADE.DTD</dtdid>
<validation>YES</validation>
<Xcollection>
<prolog>?xmlversion="1.0"?</prolog>
<doctype>!DOCTYPEFXTRADEFXTRADE.DTD</doctype>
<root_node>
<element_nodename="FXTRADE">
<RDB_node>
<tablename="FXTRADE"/>
<tablename="ACCOUNT"key="ID"/>
<condition>
FXTRADE.ACCOUNT=ACCOUNT.ID
</condition>
</RDB_node>
<element_nodename="CURRENCY1">
<text_node>
<RDB_node>
<tablename="FXTRADE"/>
<columnname="CURRENCY1"type="CHAR(3)"/>
</RDB_node>
</text_node>
</element_node>
<element_nodename="CURRENCY2">
<text_node>
<RDB_node>
<tablename="FXTRADE"/>
<columnname="CURRENCY2"type="CHAR(3)"/>
</RDB_node>
</text_node>
</element_node>
<element_nodename="AMOUNT">
<text_node>
<RDB_node>
<tablename="FXTRADE"/>
<columnname="AMOUNT"type="DECIMAL(18,2)"/>
</RDB_node>
</text_node>
</element_node>
<element_nodename="SETTLEMENT">
<text_node>
<RDB_node>
<tablename="FXTRADE"/>
<columnname="SETTLEMENT"type="DATE"/>
</RDB_node>
</text_node>
</element_node>
<element_nodename="ACCOUNT">
<element_nodename="BANKCODE">
<text_node>
<RDB_node>
<tablename="ACCOUNT"/>
<columnname="BANKCODE"type="VARCHAR(100)"/>
</RDB_node>
</text_node>
</element_node>
<element_nodename="BANKACCT">
<text_node>
<RDB_node>
<tablename="ACCOUNT"/>
<columnname="BANKACCT"type="VARCHAR(100)"/>
</RDB_node>
</text_node>
</element_node>
</element_node><!--endofAccountelement-->
</element_node><!--endofFxTradeelement-->
</root_node>
</Xcollection>
</DAD>
DAD经由过程利用element_node到RDB_node联系关系来界说在XML文档和干系数据库列之间的映照。顶层的element_nodeFXTRADE被界说为在表FXTRADE和ACCOUNT之间的毗连,带有在ACCOUNT表中的字段ID作为主键。子元素CURRENCY1被映照到在表FXTRADE中的字段CURRENCY1上,以此类推。注重ACCOUNT元素不包括任何RDB_node--这是不必要的,缘故原由是在后面已界说了ACCOUNT和FXTRADE之间的毗连。ACCOUNT、BANCCODE和BANKACCT的子元素分离的界说在ACCOUNT表中的对应的列中。原子XML元素在DAD中标志为text_node。在下面的例子中,除FXTRADE和ACCOUNT以外的一切元素都是原子的。
从数据库提取XML
经由过程存储历程来处置XML文档的分解和分化:存储历程dxxGenXML()从数据库提取XML文档;存储历程dxxShredXML()存储XML文档到数据库中。
dxxGenXML()的次要输出参数是
DAD:以DB2CLOB数据范例的情势存储;
了局表名字:机关的XML文档被转发到这个表。
其他输出参数指定前往行的最年夜数量,和<RDB_node><condition>元素摒弃(override)选项。输入参数包含前往行的实践数量,前往代码,和前往动静。
在"IBMDB2UniversalDatabaseXMLExtenderAdministrationandProgramming,Version7"中的一个C程序内、能够找到的存储历程的一个细致的例子。
存储XML在数据库中
把XML文档放进数据库中是经由过程存储历程dxxShredXML()来完成的。
dxxShredXML()的输出参数是
DAD:以DB2CLOB数据范例的情势存储;
输出XML文档:以DB2XMLCLOB数据范例的情势存储。
它的输入参数是一个前往代码和前往动静。
总结
XML-SQL映照划定规矩经由过程数据会见界说(DAD)文件的体例来指定,它是一个XML文档。DB2XMLExtender办理举措措施包含为每一个耐久的DTD机关DAD文件的一种手腕。
进一步加强将包括新的XML-SQL转换语法,它将利用XML转换言语,是W3CXSLT的一个子集。
MicrosoftSQLServer2000
SQL到XML的映照
SQLServer的SQL-to-XML和XML-to-SQL映照划定规矩利用分歧的语法。鄙人面的提取和存储段落中会商映照的概况。
从数据库提取XML
在数据库列和XML元素或属性之间的映照经由过程在SELECT中的AS别号的体例来界说:
<数据库列>AS[元素名字!嵌套级别!属性名字!唆使]
同上面一样,文档顶层被付与级别1。缺省的,映照列数据在属性值上。可使用唆使"element"来改动这个缺省设置。
从数据库天生XML的历程有两步。
步骤1。创建到你但愿输入XML中的原子元素的As-别号;别号界说了在元素之间的父/子接洽。上面的表展现给我们的例子文档的别号。
FXTRADE/*LEVEL=1*/
CURRENCY1[FXTRADE!1!CURRENCY1]
CURRENCY2[FXTRADE!1!CURRENCY2]
AMOUNT[FXTRADE!1!AMOUNT]
SETTLEMENT[FXTRADE!1!SETTLEMENT]
ACCOUNT/*LEVEL=2*/
BANKCODE[ACCOUNT!2!BANKCODE]
BANKACCT[ACCOUNT!2!BANKACCT]
步骤2。在SQL中界说输入树布局。经由过程SELECT语句界说树的每一个级别,今后经由过程UNIONALL语句的手腕把各个级别组合在一同到树中。级别-1SELECT语句参与在一切级别上的原子元素名字。每一个SELECT语句参与一个树级别标志和它的父标志。在了局会合有一个单一纪录对应于树根,好像鄙人面的第一个SELECT语句中界说的那样。
SELECT
1ASTag,
NULLASParent,
NULLAS[FXTRADE!1!CURRENCY1],
NULLAS[FXTRADE!1!CURRENCY2],
NULLAS[FXTRADE!1!AMOUNT],
NULLAS[FXTRADE!1!SETTLEMENT],
NULLAS[ACCOUNT!2!BANKCODE],
NULLAS[ACCOUNT!2!BANKACCT]
FROM
FXTRADE
UNIONALL
SELECT
2,
1,
FXTRADE.CURRENCY1,
FXTRADE.CURRENCY2,
FXTRADE.AMOUNT,
FXTRADE.SETTLEMENT,
ACCOUNT.BANKCODE,
ACCOUNT.BANKACCT
FROM
FXTRADE,ACCOUNT
WHERE
FXTRADE.ACCOUNT=ACCOUNT.ID
ORDERBY[ACCOUNT!2!BANKCODE],
[ACCOUNT!2!BANKACCT]
FORXMLEXPLICIT,ELEMENTS
FORXML经由过程剖析在组合的行会合的标志和AS-别号机关XML文档。关头字EXPLICIT选择机关XML文档的最天真的、用户界说的形式。另外一个形式AUTO经由过程使用缺省划定规矩机关XML文档。关头字ELEMENTS在元素级别建模SQL列;不然,缺省的是在属性级别建模SQL列。
存储XML在数据库中
利用OPENXML存储XML文档,它是一个新的行集函数,相似于表或视图。可使用OPENXML来拔出或更新或SELECTINTO方针表。OPENXML简化的语法展现以下:
OPENXML(<XML文档句柄>,<路径pattern>,<标记>)
WITH(形式|表)
存储XML文档的历程分三步。
利用存储历程sp_xml_preparedocument,经由过程把XML文档编译成外部DOM暗示来猎取一个XML文档句柄。
经由过程对形式字段联系关系上原子XML元从来机关一个形式。经由过程路径pattern(相对基本路径)加上绝对元素路径来界说XML元素。经由过程标记值2唆使以元素为中央的映照。可使用现存的表替换一个形式,带有等价于XML名字的字段名字。
利用存储历程sp_xml_removedocument从内存中删除编译过的XML文档。
鄙人列例子中展现这些步骤。
DECLARE@idocint
DECLARE@docvarchar(1000)
SET@doc=
<FXTRADE>
<CURRENCY1>GBP</CURRENCY1>
<CURRENCY2>JPY</CURRENCY2>
<AMOUNT>10000</AMOUNT>
<SETTLEMENT>20010325</SETTLEMENT>
<ACCOUNT>
<BANKCODE>812</BANKCODE>
<BANKACCT>00365888</BANKACCT>
</ACCOUNT>
</FXTRADE>
--创建XML文档的外部DOM暗示。
EXECsp_xml_preparedocument@idocOUTPUT,@doc
--实行利用OPENXML行集供应者的一个SELECT语句。
SELECT*
FROMOPENXML(@idoc,/FXTRADE/ACCOUNT,2)
WITH(
CURRENCY1CHAR(3),../@CURRENCY1,
CURRENCY2CHAR(3),../@CURRENCY2,
AMOUNTNUMERIC(18,2),../@AMOUNT,
SETTLEMENTDATETIME,../@SETTLEMENT,
BANKCODEVARCHAR(100),@BANKCODE,
BANKACCTVARCHAR(100),@BANKACCT)
EXECsp_xml_removedocument@idoc
总结
关于MicrosoftSQLServer2000,XML文档的提取和存档不利用对称的语法。提取经由过程利用FORXML机关扩大出一个SELECT-子句。存储参与一个行集函数OPENXML,类比于一个表或视图。提取映照划定规矩是基于(a)参与指定树级别用的标志和(b)对表的字段联系关系上在XML文档元素之间的父/子接洽。存储把XML文档重构到一个平展的形式或表中;利用XPath暗示法界说"字段-元素"联系关系。
SybaseAdaptiveServer
SQL到XML的映照
Sybase利用一个XML文档范例ResultSet来形貌XML文档元数据(元素名字、范例、巨细等)和实践的行数据两者。上面摘录自假定的FxTradeSet.xml:
<?xmlversion="1.0"?>
<!DOCTYPEResultSetSYSTEM"ResultSet.dtd">
<ResultSet>
<ResultSetMetaData>
<ColumnMetaData
...
getColumnLabel="CURRENCY1"
getColumnName="CURRENCY1"
getColumnType="12"
.../>
...
</ResultSetMetaData>
<ResultSetData>
<Row>
<Columnname="CURRENCY1">GBP</Column>
...
</Row>
</ResultSetData>
</ResultSet>
ResultSetDTD仿佛不同意嵌套元素的界说。
从数据库提取XML
Java类ResultSetXml有一个机关器,它承受一个SQL查询作为参数,今后getXmlLText办法从了局集提取个XML文档:
jcs.xml.resultset.ResultSetXmlrsx=newjcs.xml.resultset.ResultSetXml
("Select*fromFxTrade",<otherparameters>);
FileUtil.string2File("FxTradeSet.xml",rsx.getXmlText());
存储XML在数据库中
ResultSetXml类机关器也承受一个XML文档作为参数。今后办法toSqlScript天生SQL语句的序列来从了局集拔出/更新到指定的表。
StringxmlString=FileUtil.file2string("FxTradeSet.xml");
jcs.xml.resultset.ResultSetXmlrsx=newjcs.xml.resultset.ResultSetXml
(xmlString);
StringsqlString=rsx.toSqlScript("FxTrade",<otherparameters>)
总结
XML文档的提取和存储是实质上对称的。存储仿佛不同意修正多于一个表。提取把SQL查询的了局转换到有平展布局的文档中。
厂商对照
厂商映照划定规矩单一表/多个表转化的手腕对称的提取/存储
Oracle隐含的;经由过程机关对象-干系模子多个指定的Java类对称,假如XML文档和对象-干系模子婚配
IBM数据会见界说文件多个指定的存储历程对称
MicrosoftSQL扩大;行集函数多个表用于提取;单一表用于存储经由过程利用SQL机关FORXML和行集OPENXML不合错误称
Sybase了局集DTD单一表;查询能够包括多个表经由过程利用Java类对称
厂商间的大众特性是:
XML耐久性创建在出格的基本上,就是说,没有一样平常性的举措措施来存储恣意XML文档);假如XML文档利用一个新的文法例必要专门的映照;
存储常常必要数据处置,好比依照利用的地区来从头格局化数值/日期;能够使用XSLT来举行XML数据收拾。
一种可替换的战略
XML文档存储在数据库中的义务能够分别到阶段?起首,存储XML在一般的数据库布局中而不该用任何映照划定规矩;其次,为后续的处置供应一个框架?这类办法的优点是关于现实上的任何XML文档有一个通用的收罗代办署理(acquisitionagent)。本文的余下部分只发起这类办理体例。
在这类战略下,XML文档保留为一般的树布局――原始树数据――用于进一步的使用处置。进一步数据处置的框架是一组数据库对象(存储历程),相似于DOMAPI,用来经由过程传统的SQL处置来利用数据。
利用与全主动体例相反的框架体例的优点有:数据库群体(population)一般由散布在"纯"使用程序代码、事件处置、数据库层(layer)和存储历程之间的使用逻辑来把持的,不用说起一些表大概驻留在远端数据库中。
别的,在异构的数据库情况中,具有一个一致的工具来对分歧的数据库完成不异的义务有着分明的优点。
作者的办理计划,ObjectCentricSolutionsx-PersistenceUtility,完成了这里会商的战略。
原始树布局经由过程以下表来界说。
1)树节点界说
CREATETABLENodeDef(
nodeIDudd_idNOTNULL,//独一性节点id
dimIDudd_idNOTNULL,//树品种:XML
nameudd_nameNOTNULL,//节点名字
valueudd_paramvalueNULL,//节点值
value_typeudd_typeNULL,//值范例
powerudd_powerNULL,//节点树级别
isRootudd_logicalNOTNULL,//顶层节点标记
descriptorudd_descriptorNULL,//DOM节点范例
colorudd_colorNULL//非正式数据
)
2)在节点间的父-子干系
CREATETABLENodeLinks(
parentIDudd_idNOTNULL,//父节点
childIDudd_idNOTNULL//子节点
)
用例
存储XML文档在数据库中必要挪用XML2SQL程序:
XML2SQL<XML文档文件名>
利用以下存储历程完成从数据库提取XML文档为一个树布局:
get_tree_roots<树品种>--提取一个给定丛林的一切文档根id
get_tree<根id>--提取一个给定根(文档)的一切节点
get_children<节点,级别>--提取一个给定节点的特定级其余一切子节点
完成细节:
以后的平台包含:Sybase,MSSQLServer。
被评价的平台:Oracle,DB2和PostgreSQL。
有用工具创建在XercesXML剖析器顶上。
数据库安装触及到的只是增添一些表,和导航数据库表为树布局的存储历程。
x-PersistenceUtility以后在OpenFinanceLaboratory顶用作基于XML的数据收罗代办署理的中心,它是如证券办理、欠债办理、风险办理等局限内的财政使用的一个可定制的集成平台。OpenFinanceLaboratory承受FpML作为用于利率导出的一个叙说性言语。x-PersistenceUtility今朝用作FpML/FRA数据收罗代办署理。
恰恰证明了java的简单,要不怎么没有通过c/c++来搞个这种框架? |
|