下一代數據庫驅動將拋棄 ODBC/JDBC 等低層 API,轉而採用 SOAP/REST 高層協議,使數據庫直接成為 SOA 參與者。本文提供一個 DB2 SOAP 驅動程序示例,通過隱式調用存儲過程實現無映射集成。


表結構:CUSTOMERS(CUSTID, CC VARCHAR FOR BIT DATA, INFO XML),信用卡加密存儲。
INSERT INTO CUSTOMERS VALUES ('hardeep',
ENCRYPT('<CC type="visa" number="4721930402892796" cvv="808"><name>hardeep</name></CC>', 'passWord'),
'<Customer customerid="hardeep" firstname="hardeep" lastname="singh"/>');


var cid = document.getElementById("userid").value;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', servletpath + "?cmd=customerinfo&msg=" + cid, true);
xmlhttp.onreadystatechange = function() { getCustomerInfoCallback(xmlhttp); };
xmlhttp.send("");
Connection conn = DriverManager.getConnection("jdbc:db2:article4");
Statement stmt = conn.createStatement();
stmt.setMaxRows(1);
ResultSet rs = stmt.executeQuery("SELECT info FROM customers WHERE custid='" + msg + "'");
if (rs.next()) retValue = rs.getString(1);
stmt.close(); conn.close();
響應頭 Content-Type: text/xml 直接返回 XML。


var req = 'OTA_HotelSearchRQ xmlns="https://www.opentravel.org/OTA/2003/05" ... '
+ '<HotelRef HotelCityCode="' + citycode + '"/> ... </OTA_HotelSearchRQ>';
var msg = '<request cmd="hotelrates">' + req + '</request>';
// AJAX POST 發送
String body = "<db:getHotelRates xmlns:db='https://ibm.com/db2/soap'>"
+ "<db:arg>" + msg + "</db:arg></db:getHotelRates>";
return sendURLMessage("https://localhost:8080/article4/db2soapdriver", body, "https://ibm.com/db2/soap#article4");
SOAPAction 設置為目標數據庫名。sendURLMessage 手工構造 SOAP Envelope,證明 SOAP 本質是標準化的 HTTP POST。
CREATE PROCEDURE getHotelRates(IN request XML)
DYNAMIC RESULT SETS 1 LANGUAGE SQL
BEGIN
DECLARE c_cur CURSOR WITH RETURN FOR
SELECT XMLQUERY('declare namespace ns1="https://www.opentravel.org/OTA/2003/05";
$info//ns1:HotelDescriptiveContents' PASSING info AS "info")
FROM hotel
WHERE XMLEXISTS('declare namespace ns1="https://www.opentravel.org/OTA/2003/05";
$info//ns1:HotelDescriptiveContents[@HotelCityCode=$req//ns1:HotelRef/@HotelCityCode]'
PASSING request AS "req", info AS "info");
OPEN c_cur;
END
SOAP 響應原樣透傳回客戶端,服務端僅作中介。
var soapxml = new xmlparse(xmlhttp.responseXML, false);
soapxml.XMLRoot.setProperty("SelectionNamespaces",
"xmlns:SOAP-ENV='https://schemas.xmlsoap.org/soap/envelope/' xmlns:db='https://ibm.com/db2/soap'");
soapxml.find("//SOAP-ENV:Body//db:row", null, true);
for (var i=0; i<soapxml.currentFind.length; i++) {
var row = new XMLparse(soapxml.getValue("db:col/text()", i), true);
row.setNamespaces("xmlns:x='https://www.opentravel.org/OTA/2003/05'");
var id = row.getValue("//x:HotelDescriptiveContents/@HotelCode");
var name = row.getValue("//x:HotelName/@HotelShortName");
var rooms = row.getValue("//x:GuestRoomInfo/@Quantity");
var charge = row.getValue("//x:Charge/@Amount");
// 渲染酒店列表,綁定 bookRoom(hotelId, charge)
}


function bookRoom(hotelid, amount) {
var msg = '<request cmd="bookroom"><message><ccinfo units="1" amount="' + amount + '"/>'
+ '<username>' + cid + '</username><hotelid>' + hotelid + '</hotelid></message></request>';
// AJAX POST
}
String userid = msgXML.getValue("//username/text()");
ResultSet rs = stmt.executeQuery("SELECT info, DECRYPT_CHAR(CC,'passWord') FROM customers WHERE custid='" + userid + "'");
if (rs.next()) {
String custinfo = rs.getString(1);
String body = "<db:bookaroom xmlns:db='https://ibm.com/db2/soap'>"
+ "<db:arg>" + hotelid + "</db:arg>"
+ "<db:arg>" + custinfo + "</db:arg>"
+ "<db:arg></db:arg></db:bookaroom>";
sendURLMessage("https://localhost:8080/article4/db2soapdriver", body, "https://ibm.com/db2/soap#article4");
}
DB2 SOAP 驅動程序原型預示了數據庫即服務的未來:標準協議、原生 XML、業務邏輯下推,讓集成更簡潔、更敏捷。