SAPUI5 (26) - 基于 ODataModel 的增刪改查

http://services.odata.org 提供了允許進行 CRUD 的 OData 數(shù)據(jù)服務 ( OData data service )妆艘,版本為 v2,可以通過 http://services.odata.org/V2/(S(user-session-token))/OData/OData.svc/ 訪問麸祷。其中 user-session-token 需要替換成進入時網(wǎng)站分配的的 token , CRUD 也僅對該 Session 有效。

本篇介紹基于 OData v2,對 Northwind online data service 進行 CRUD 操作楚殿。介紹的重點包括:

  • http 請求侠畔;
  • 使用 Postman 發(fā)送 http 請求结缚;
  • 使用 ODataModel (v2) 提交 CRUD 方法和查看返回結果。

讀取數(shù)據(jù)

OData Service 讀取數(shù)據(jù)(Read)

讀取 OData service 提供的數(shù)據(jù)软棺,通過 http 的 GET 方法红竭。如果請求成功,返回的狀態(tài)碼為 200喘落,如果請求的資源不存在茵宪,返回的狀態(tài)碼為 404.。請求的數(shù)據(jù)可以是一個實體瘦棋,也可以是一個集合 ( Set )稀火。

我們先借助 Postman 這個 Chrome 插件來查看 Northwind 數(shù)據(jù)服務。我們來查看第一個供應商的信息赌朋。操作界面:

  • 要點

    • URL: http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/Suppliers(0)?$format=json
    • Method type: GET

返回的結果:如上圖所示凰狞。

ODataModel (v2) 讀取 Odata 數(shù)據(jù)

首先指定 Service URL,因為 Same-origin 原因沛慢,使用代理( 請?zhí)鎿Q成自己的 user-session-token ):

var sServiceUrl = "https://cors-anywhere.herokuapp.com/" 
                + "http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/";

讀取數(shù)據(jù)的操作放在 readSupplier() 函數(shù)中:

// 讀取供應商
function readSupplier(){
    var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);     
    
    function fnSuccess(oData, oResponse){
        console.log("Response", oResponse);
        console.log("Data", oData);
    }
    
    function fnError(oError){
        console.log("Error", oError);
    }
    
    // 讀取存在的 supplier
    oModel.read("/Suppliers(0)", {
        success: fnSuccess,
        error: fnError
    });
    
    // 故意讀取一個不存在的 supplier
    oModel.read("/Suppliers(12222)", {
            success: fnSuccess,
            error: fnError
    });
}

在 Chrome 瀏覽器中運行赡若,按下 F12, 在開發(fā)者工具的 Console 選項卡中查看結果,因為第一次第一次讀取的供應商 ID 存在团甲,所以返回 200 狀態(tài)碼逾冬,成功。這是讀取第一個供應商返回的對象:

因為第二個供應商不存在躺苦,所以返回錯誤狀態(tài)碼 404 - Not found粉渠。下圖是讀取第二個供應商返回的錯誤的界面:

07.png

ODataModel 讀取數(shù)據(jù)的要點

  • ODataModelread() 方法觸發(fā)一個 GET 請求分冈,如果請求成功,執(zhí)行 success 回調(diào)函數(shù)霸株,該函數(shù)的 oData 參數(shù)包含 response 返回的數(shù)據(jù)雕沉,失敗則執(zhí)行 error 回調(diào)函數(shù)。

  • 請求后返回的數(shù)據(jù)緩存在 OData model 中去件,可以調(diào)用 getData() 方法(這個方法已經(jīng)廢棄)坡椒,這個方法返回整個實體 ( Entity ) ; 調(diào)用 getProperty() 方法,返回實體中的某一屬性尤溜。這兩個方法都不觸發(fā) http 請求倔叼,所以獲得的是已經(jīng)請求過并保存在緩存中的數(shù)據(jù)。示例如下:

// 讀取 OData model 緩存的數(shù)據(jù)
function getData(){        
    var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);     
    
    oModel.read("/Suppliers", {        
        success: function(oData, oResponse){
            // 兩種方法讀取 supplier name
            var oSupplier = oModel.getData("/Suppliers(1)");
            console.log(oSupplier.Name);  // 方法1
            console.log(oModel.getProperty("/Suppliers(1)/Name"));  // 方法2
        },
        
        error: function(oError){
            console.log("Error", oError);
        }
    });         
}
  • oDataModel.read() 方法從 OData data service 獲取所有供應商放在 oModel 的緩存中宫莱,然后通過 getData("/Suppliers(0)") 獲取第一個供應商丈攒。因為 oSupplier 是一個對象,所以可以通過 oSupplier.Name 獲取供應商名稱授霸,也可直接通過 oModel.getProperty("/Suppliers(0)/Name) 獲取供應商名稱巡验。

  • OData data service 的元數(shù)據(jù) ( metadata ) 在 read() 方法調(diào)用后后被加載到客戶端緩存。如果多個 OData model 使用同一個 url碘耳,則它們共享一個元數(shù)據(jù)显设,只有第一個 model 的請求會觸發(fā)獲取 $metadata 請求。元數(shù)據(jù)的加載是異步的辛辨,并且也不能被設置為同步的捕捂。元數(shù)據(jù)是 XML 格式的,但 OData modelgetServiceMetadata() 獲取到的 model 元數(shù)據(jù)為元數(shù)據(jù)所對應的 json 格式斗搞。

新建數(shù)據(jù)

OData Service 可以使用 HTTP 協(xié)議的 POST 方法提交創(chuàng)建數(shù)據(jù)的請求指攒,如果成功,返回的狀態(tài)碼為 201僻焚。

在 Chrome 插件 Postman 中提交 POST 請求幽七,可以先用 GET 方法讀取一條數(shù)據(jù),然后將返回的數(shù)據(jù)拷貝出來進行修改的方式溅呢,簡化操作過程澡屡。比如,我們想要創(chuàng)建一個新供應商咐旧,編號為 #101:

在 Postman 中驶鹉,選擇 POST 方法,URL 中輸入:http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/Suppliers铣墨。POST 請求的 URL 是一個集合室埋。然后切換到 headers ,指定 Content-typeapplication/json

041.png

最后再切換到 Body姚淆,使用 Raw 格式孕蝉,編寫要提交的數(shù)據(jù):

使用 ODataModel 創(chuàng)建供應商

// 創(chuàng)建供應商
function createSupplier(){
    var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);
    oModel.setUseBatch(false);
    oModel.setHeaders({
        "Content-type":"application/json"
    });
    
    function fnSuccess(oData, oResponse){
        console.log("Response", oResponse);
    }
    
    function fnError(oError){
        console.log("Error", oError);
    }
    
    var oNewSupplier = {
            "ID": 101,
            "Name": "Stone測試供應商#101",
            "Address": {
                "Street": "三角湖路",
                "City": "武漢",
                "State": "HB",
                "ZipCode": "430060",
                "Country": "中國"
            }
        };
    
    oModel.create("/Suppliers", oNewSupplier, {
        success: fnSuccess,
        error: fnError
    });             
}

修改數(shù)據(jù)

修改數(shù)據(jù)使用 PUT 方法,在 Postman 中操作時腌逢,選擇 PUT 方法降淮,URL 為:http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/Suppliers(101),Headers 頁面添加 Content-type 和 If-match:

然后到 Body 頁面搏讶,選擇 Raw佳鳖,編輯需要修改的數(shù)據(jù)。如果請求成功媒惕,返回狀態(tài)碼為 204 - No content系吩。

使用 ODataModel 修改數(shù)據(jù)的代碼:

// 修改供應商
function editSupplier(){
    var oModel = new sap.ui.model.odata.v2.ODataModel({
        serviceUrl: sServiceUrl,
        headers: {
            "If-match": "*"
        }});
    
    var oChanges = {                        
            "Name": "Stone測試供應商#101",
            "Address": {
                "Street": "博學路",
                "City": "武漢",
                "State": "HB",
                "ZipCode": "430060",
                "Country": "China"
            }
        };
    oModel.update("/Suppliers(101)", oChanges, {
        success: function(oData, oResponse){
            console.log("Response", oResponse);
        },
        error: function(oError){
            console.log("Error", oError);
        }
    });
}

刪除數(shù)據(jù)

刪除 OData 的數(shù)據(jù)使用 DELETE 方法,在 Postman 中操作時妒蔚,選擇 DELETE 方法穿挨,URL 為:http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/Suppliers(101)。Headers 需要指定 If-match:

因為刪除數(shù)據(jù)不需要提交額外的數(shù)據(jù)肴盏,所以 Body 部分為空科盛。如果請求成功,返回的狀態(tài)碼為 204 - No content叁鉴。

使用 ODataModel 刪除數(shù)據(jù)的代碼如下:

// 刪除供應商
function deleteSupplier(){  
    var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);     
    
    // set headers
    oModel.setHeaders({
        "If-match": "*"
    });
    
    oModel.remove("/Suppliers(101)", {
        success: function (oData, oResponse){
            console.log(oResponse);
        }, 
        error: function (oError){
            console.log(oError);
        }
    });             
}       

最后給出測試的完整代碼:

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>

        <script src="../../resources/sap-ui-core.js"
                id="sap-ui-bootstrap"
                data-sap-ui-libs="sap.m"
                data-sap-ui-theme="sap_bluecrystal">
        </script>
        <!-- only load the mobile lib "sap.m" and the "sap_bluecrystal" theme -->

        <script>
            var sServiceUrl = "https://cors-anywhere.herokuapp.com/" 
                            + "http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/";
                        
            // 讀取供應商
            function readSupplier(){
                var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);     
                
                function fnSuccess(oData, oResponse){
                    console.log("Response", oResponse);
                    console.log("Data", oData);
                }
                
                function fnError(oError){
                    console.log("Error", oError);
                }
                
                // 讀取存在的 supplier
                oModel.read("/Suppliers(0)", {
                    success: fnSuccess,
                    error: fnError
                });
                
                // 讀取不存在的 supplier
                oModel.read("/Suppliers(12222)", {
                        success: fnSuccess,
                        error: fnError
                });
            }
            
            // 讀取 OData model 緩存的數(shù)據(jù)
            function getData(){        
                var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);     
                
                oModel.read("/Suppliers", {
                    
                    success: function(oData, oResponse){
                        // 兩種方法讀取 supplier name
                        var oSupplier = oModel.getData("/Suppliers(1)");
                        console.log(oSupplier.Name);
                        console.log(oModel.getProperty("/Suppliers(1)/Name"));
                    },
                    
                    error: function(oError){
                        console.log("Error", oError);
                    }
                });         
            }

            // 創(chuàng)建供應商
            function createSupplier(){
                var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);
                oModel.setUseBatch(false);
                oModel.setHeaders({
                    "Content-type":"application/json"
                });
                
                function fnSuccess(oData, oResponse){
                    console.log("Response", oResponse);
                }
                
                function fnError(oError){
                    console.log("Error", oError);
                }
                
                var oNewSupplier = {
                        "ID": 101,
                        "Name": "Stone測試供應商#101",
                        "Address": {
                          "Street": "三角湖路",
                          "City": "武漢",
                          "State": "HB",
                          "ZipCode": "430060",
                          "Country": "中國"
                        }
                    };
                
                oModel.create("/Suppliers", oNewSupplier, {
                    success: fnSuccess,
                    error: fnError
                });             
            }
            
            // 修改供應商
            function editSupplier(){
                var oModel = new sap.ui.model.odata.v2.ODataModel({
                    serviceUrl: sServiceUrl,
                    headers: {
                        "If-match": "*"
                    }});
                
                var oChanges = {                        
                        "Name": "Stone測試供應商-#101",
                        "Address": {
                          "Street": "博學路",
                          "City": "武漢",
                          "State": "HB",
                          "ZipCode": "430060",
                          "Country": "China"
                        }
                    };
                oModel.update("/Suppliers(101)", oChanges, {
                    success: function(oData, oResponse){
                        console.log("Response", oResponse);
                    },
                    error: function(oError){
                        console.log("Error", oError);
                    }
                });
            }
            
            // 刪除供應商
            function deleteSupplier(){  
                var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl);     
                
                // set headers
                oModel.setHeaders({
                    "If-match": "*"
                });
                
                oModel.remove("/Suppliers(101)", {
                    success: function (oData, oResponse){
                        console.log(oResponse);
                    }, 
                    error: function (oError){
                        console.log(oError);
                    }
                });             
            }           

        
            sap.ui.getCore().attachInit(function(){                     
                var oReadButton = new sap.m.Button({
                    text: "Read",
                    press: readSupplier
                });
                
                var oGetDataButton = new sap.m.Button({
                    text: "Get data",
                    press: getData
                });
                
                var oCreateButton = new sap.m.Button({
                    text: "Create",
                    press: createSupplier
                });
                
                var oEditButton = new sap.m.Button({
                    text: "Edit",
                    press: editSupplier
                });
                
                var oDeleteButton = new sap.m.Button({
                    text: "Delete",
                    press: deleteSupplier
                });
                
                var oPage = new sap.m.Page({
                    title: "基于oData Model的增刪改查",
                    content: [oReadButton, oGetDataButton, oCreateButton, oEditButton, oDeleteButton]
                });
                
                var oApp = new sap.m.App({
                    initialPage: oPage
                });
                
                oApp.addPage(oPage);
                oApp.placeAt("content");                
            });         
            
        </script>

    </head>
    <body class="sapUiBody" role="application">
        <div id="content"></div>
    </body>
</html>

源代碼

26_zui5_odata_crud_northwind

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市佛寿,隨后出現(xiàn)的幾起案子幌墓,更是在濱河造成了極大的恐慌,老刑警劉巖冀泻,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件常侣,死亡現(xiàn)場離奇詭異,居然都是意外死亡弹渔,警方通過查閱死者的電腦和手機胳施,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肢专,“玉大人舞肆,你說我怎么就攤上這事〔┱龋” “怎么了椿胯?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剃根。 經(jīng)常有香客問我哩盲,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任廉油,我火速辦了婚禮惠险,結果婚禮上,老公的妹妹穿的比我還像新娘抒线。我一直安慰自己班巩,他們只是感情好,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布十兢。 她就那樣靜靜地躺著趣竣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旱物。 梳的紋絲不亂的頭發(fā)上遥缕,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天,我揣著相機與錄音宵呛,去河邊找鬼单匣。 笑死,一個胖子當著我的面吹牛宝穗,可吹牛的內(nèi)容都是我干的户秤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逮矛,長吁一口氣:“原來是場噩夢啊……” “哼鸡号!你這毒婦竟也來了?” 一聲冷哼從身側響起须鼎,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鲸伴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后晋控,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體汞窗,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年赡译,在試婚紗的時候發(fā)現(xiàn)自己被綠了仲吏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蝌焚,死狀恐怖裹唆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情只洒,我是刑警寧澤品腹,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站红碑,受9級特大地震影響舞吭,放射性物質(zhì)發(fā)生泄漏泡垃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一羡鸥、第九天 我趴在偏房一處隱蔽的房頂上張望蔑穴。 院中可真熱鬧,春花似錦惧浴、人聲如沸存和。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捐腿。三九已至,卻和暖如春柿顶,著一層夾襖步出監(jiān)牢的瞬間茄袖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工嘁锯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宪祥,地道東北人。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓家乘,卻偏偏與公主長得像蝗羊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子仁锯,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容