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

http://services.odata.org 提供了允许进行 CRUD 的 OData 数据服务 ( OData data service ),版本为 v2,可以通过 http://services.odata.org/V2/(S(user-session-token))/OData/OData.svc/ 访问。其中 user-session-token 需要替换成进入时网站分配的的 token , CRUD 也仅对该 Session 有效。

本篇介绍基于 OData v2,对 Northwind online data service 进行 CRUD 操作。介绍的重点包括:

  • http 请求;
  • 使用 Postman 发送 http 请求;
  • 使用 ODataModel (v2) 提交 CRUD 方法和查看返回结果。

读取数据

OData Service 读取数据(Read)

读取 OData service 提供的数据,通过 http 的 GET 方法。如果请求成功,返回的状态码为 200,如果请求的资源不存在,返回的状态码为 404.。请求的数据可以是一个实体,也可以是一个集合 ( Set )。

我们先借助 Postman 这个 Chrome 插件来查看 Northwind 数据服务。我们来查看第一个供应商的信息。操作界面:

SAPUI5 (26) - 基于 ODataModel 的增删改查_第1张图片

  • 要点

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

返回的结果:如上图所示。

ODataModel (v2) 读取 Odata 数据

首先指定 Service URL,因为 Same-origin 原因,使用代理( 请替换成自己的 user-session-token ):

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

读取数据的操作放在 readSupplier() 函数中:

// 读取供应商
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, 在开发者工具的 Console 选项卡中查看结果,因为第一次第一次读取的供应商 ID 存在,所以返回 200 状态码,成功。这是读取第一个供应商返回的对象:

SAPUI5 (26) - 基于 ODataModel 的增删改查_第2张图片

因为第二个供应商不存在,所以返回错误状态码 404 - Not found。下图是读取第二个供应商返回的错误的界面:

SAPUI5 (26) - 基于 ODataModel 的增删改查_第3张图片

ODataModel 读取数据的要点

  • ODataModelread() 方法触发一个 GET 请求,如果请求成功,执行 success 回调函数,该函数的 oData 参数包含 response 返回的数据,失败则执行 error 回调函数。

  • 请求后返回的数据缓存在 OData model 中,可以调用 getData() 方法(这个方法已经废弃),这个方法返回整个实体 ( Entity ) ; 调用 getProperty() 方法,返回实体中的某一属性。这两个方法都不触发 http 请求,所以获得的是已经请求过并保存在缓存中的数据。示例如下:

// 读取 OData model 缓存的数据
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 的元数据 ( metadata ) 在 read() 方法调用后后被加载到客户端缓存。如果多个 OData model 使用同一个 url,则它们共享一个元数据,只有第一个 model 的请求会触发获取 $metadata 请求。元数据的加载是异步的,并且也不能被设置为同步的。元数据是 XML 格式的,但 OData modelgetServiceMetadata() 获取到的 model 元数据为元数据所对应的 json 格式。

新建数据

OData Service 可以使用 HTTP 协议的 POST 方法提交创建数据的请求,如果成功,返回的状态码为 201。

在 Chrome 插件 Postman 中提交 POST 请求,可以先用 GET 方法读取一条数据,然后将返回的数据拷贝出来进行修改的方式,简化操作过程。比如,我们想要创建一个新供应商,编号为 #101:

在 Postman 中,选择 POST 方法,URL 中输入:http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/Suppliers。POST 请求的 URL 是一个集合。然后切换到 headers ,指定 Content-typeapplication/json

SAPUI5 (26) - 基于 ODataModel 的增删改查_第4张图片

最后再切换到 Body,使用 Raw 格式,编写要提交的数据:

SAPUI5 (26) - 基于 ODataModel 的增删改查_第5张图片

使用 ODataModel 创建供应商

// 创建供应商
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
    });			    
}

修改数据

修改数据使用 PUT 方法,在 Postman 中操作时,选择 PUT 方法,URL 为:http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/Suppliers(101),Headers 页面添加 Content-type 和 If-match:

SAPUI5 (26) - 基于 ODataModel 的增删改查_第6张图片

然后到 Body 页面,选择 Raw,编辑需要修改的数据。如果请求成功,返回状态码为 204 - No content。

SAPUI5 (26) - 基于 ODataModel 的增删改查_第7张图片

使用 ODataModel 修改数据的代码:

// 修改供应商
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);
        }
    });
}

删除数据

删除 OData 的数据使用 DELETE 方法,在 Postman 中操作时,选择 DELETE 方法,URL 为:http://services.odata.org/V2/(S(tigt4zfne0egj3u25bhqq32a))/OData/OData.svc/Suppliers(101)。Headers 需要指定 If-match:

SAPUI5 (26) - 基于 ODataModel 的增删改查_第8张图片

因为删除数据不需要提交额外的数据,所以 Body 部分为空。如果请求成功,返回的状态码为 204 - No content。

使用 ODataModel 删除数据的代码如下:

// 删除供应商
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);
        }
    });		        
}		

最后给出测试的完整代码:


<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>
		

		<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 缓存的数据
			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);
	        		}
	        	});        	
	        }

			// 创建供应商
			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

你可能感兴趣的:(SAPUI5)