This blog post is about Deferred Groups and Change Groups. If not explicitly disabled, the sap.ui.model.odata.v2.ODataModel
uses batch processing. In batch processing the ODataModel sends one or more OData requests in a single $batch http request. Using the so called groupId
you can bundle specific OData requests in different $batch requests. This lets you optimize your data management in your application.
A groupId can be Immediate or Deferred.
Immediate
The OData requests created within a JavaScript function are collected and sent in a $batch request in a timeout immediately after the current call stack is finished.
Deferred
The OData requests are stored, and the $batch request for them is only sent when the method submitChanges
of the ODataModel gets called with the corresponding groupId as parameter.
Deferred Groups
The default deferred group is “changes”. You can check it via getDeferredGroups
.
this.getModel().getDeferredGroups(); //Expected output: ['changes']
You can define groups via setDeferredGroups
.
this.getModel().setDeferredGroups(["a", "b"]); this.getModel().getDeferredGroups(); //Expected output: ['a', 'b']
🛎️ Important
If you overwrite the default deferred group “changes” you may experience immediate $batch requests. That’s cause you “destroyed” the default settings. More about this in Change Groups.
Usually you want to add a group, but not define all of them or overwrite existing ones. For this i use the following function.
_createGroupId
_createGroupId: function (sGroupId) { var oServiceModel = this.getView().getModel(), //may adjustment necessary aDeferredGroup = oServiceModel.getDeferredGroups(); //Add a new GroupId if (!aDeferredGroup.includes(sGroupId)) { aDeferredGroup.push(sGroupId); oServiceModel.setDeferredGroups(aDeferredGroup); } }
Example
this.getModel().getDeferredGroups(); //Expected output: ['changes'] this._createGroupId("a"); this.getModel().getDeferredGroups(); //Expected output: ['changes', 'a'] this._createGroupId("a"); this.getModel().getDeferredGroups(); //Expected output: ['changes', 'a'] this._createGroupId("b"); this.getModel().getDeferredGroups(); //Expected output: ['changes', 'a', 'b']
Change Groups
By default every OData request will be stored in the deferred group “changes”. You can check it via getChangeGroups
.
this.getModel().getChangeGroups(); //Expected output: {"*":{"groupId":"changes"}}
🛎️ Important
As mentioned above, if you overwrite the default deferred group “changes” you may experience immediate $batch requests. That’s cause by default every OData requests will be assigned to the groupId “changes”. If the group is not declared as an deferred group, its immediate.
If you just declare a new deferred group nothing changes. You have to code that specific changes should be bundled in the added deferred group. For that you can use setChangeGroups
.
The following coding defines two new deferred groups. Every change in an entity of the EntitySetA should be captured in the group “groupForEntitySetA”. Every change in an Entity of the EntitySetB should be captured in the group “groupForEntitySetB”. This allows seperate data processing of the two entitysets.
this._createGroupId("groupForEntitySetA"); this._createGroupId("groupForEntitySetB"); this._oServiceModel.setChangeGroups({ "EntitySetA": { groupId: "groupForEntitySetA"//, //changeSetId: "A" //ID of a ChangeSet which bundles the changes for the entity type. //single: true //Defines if every change will get an own change set (defaults to true) }, "EntitySetB": { groupId: "groupForEntitySetB"//, //changeSetId: "B" //ID of a ChangeSet which bundles the changes for the entity type. //single: true //Defines if every change will get an own change set (defaults to true) } });
Submit Changes
When working with deferred groups the $batch request is only sent when the method submitChanges
gets called. If you do not specify a batch group ID when calling submitChanges, all deferred batch groups are submitted.
var oServiceModel = this.getModel(); oServiceModel.submitChanges({ groupId: "groupForEntitySetA", success: function(oResponse) { //do sth. (process batch responses) }.bind(this), error: function(oErr) { //do sth. (error handling) //busi exceptions in $batch are handled as success //only dumps/technical errors are handled as error }.bind(this) });
✨ Recommendation
Check out the following code snippet: How to process errors in batch responses.
Other ways to set the groupId
Apart from the method setChangeGroups
, there are many other ways to assign a groupId to an OData request.
createEntry
If you create an data entry via createEntry
you can pass the groupId as a parameter. This way you can handle specific OData create requests seperately if needed.
_createDraft: function () { var oServiceModel = this.getView().getModel(); var oContext = oServiceModel.createEntry("CarrierCollection", { groupId: this._createGroupId("CarrierCreation"), properties: { carrid: "", CARRNAME: "", CURRCODE: "EUR", URL: "" } }); return oContext.getPath(); }
✨ Recommendation
For an full example check out the blog post: An Recommendation for creating Data Form Dialogs in SAPUI5
xml binding
When binding a aggregation in your xml view you can define a groupId. Changes made via two-way binding will lead to OData requests that are bundled into the specified groupId.
items="{ path: '/MyEntitySet', parameters: { groupId: 'groupIdA' } }"
manual requests
- callFunction
- create
- remove
- update