Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
CarlosRoggan
Product and Topic Expert
Product and Topic Expert

Hello syambabu.allu


How are you?

Hope you’re doing good and enjoying nice summer vacation.
Has been nice to receive your comment in my previous blog
I think we’re following each other already since many years…and it's nice to see you're still active and enthusiastic community member...?
I’ve thought of writing you a letter to answer your question.

This has been your comment:







Great Blog on Deep Insert.Thank you for sharing this.


is that possible to create Multi-level deep insert using above approach.


Thank you,
Syam



First of all, thanks very much for your feedback!
I’d even say, thank you very much for it!
It is thanks to colleagues like YOU that encourage us to continue publishing and sharing findings…
Please continue with your generous words ?

Now coming to your question: multi-level deep insert
I have good news for you:
Yes, my friend, it is possible.

I understand you and your necessities:
You have modelled a beautiful CDS which allows to navigate from one Entity to the next one:
entity CompanyEntity {
. . .
linkToContact : Association to ContactEntity;
}

entity ContactEntity {
. . .
linkToCommunication : Association to CommunicationEntity;
}

entity CommunicationEntity {
. . .
linkToComment : Association to CommentEntity;
}

entity CommentEntity {
. . .
message : String;
}

and now you want to create all nice data with one deep insert request, like this:
{
"companyId": 1,
. . .
"linkToContact":
{
"contactId": 11,
. . .
"linkToCommunication":
{
"communicationId": 111,
. . .
"linkToComment":
{
"commentId": 1111,
. . .

And you want to know whether it is possible?
I have good news for you...
The short answer is: yes
The friendly answer: yes my friend
The long answer: you just need to add more entries to the key map
The very long cryptic answer:
keyMap.put("linkToCommunication", Collections.singletonList("communicationId"));           
keyMap.put("linkToComment", Collections.singletonList("commentId"))

The extremely long and detailed and helpful answer:
OK, I can describe everything I did.
And for your convenience, my friend, I'll attach all sample files to this letter 😉

Create Project


I’ve created a CAP project with name DeepInsertMulti
It has java package com.example and uses database and prefers OData version 2

CDS


I’ve used a little model which I’m attaching to this letter
And I’ve used a little service definition, also attached

Custom Java Code


Then I’ve overwritten the CREATE operation for the entity on which the multi-level deep insert is executed:
@Create(entity = "CompanyEntity", serviceName = "RelationService")
public CreateResponse createCompanyDeep(CreateRequest createRequest, ExtensionHelper extensionHelper) throws DatasourceException{

And I’ve created the required code like I described in my previous blogs here and here

As you know, the map is used by the framework to gather information about which is the key property for every entity to create
With other words, they CREATE payload contains multiple nested maps and for each map, an entry is created in the database and the FWK has to know which entity and which key field. So the map contains one entry for the top-level entity, where the key property is mapped to the entity itself
keyMap.put("CompanyEntity", Collections.singletonList("companyId"));        

For each nested map, I’ve created an entry where the key property is mapped to the Association
keyMap.put("linkToContact", Collections.singletonList("contactId"));                
keyMap.put("linkToCommunication", Collections.singletonList("communicationId"));
keyMap.put("linkToComment", Collections.singletonList("commentId"));

You know me, my friend, and as you know, I prefer to give names which make everything very clear. Thanks to this, the above example code makes clear what I described before: the names of entity and associations

See the full java class in the attachment of this mail.

MTA


Finally, I’ve done the 2 small modifications to the mta.yaml file, as described in previous blog

Deploy


Then I deployed the project

Test


After deployment, I checked the metadata document, to see if the 4 entities and the 4 navigation links looked as expected:
https://p123trial-subacc-space-deepinsertmulti-srv.../v2/RelationService/$metadata

Then I composed the request for a deep insert as follows:



























HTTP Verb
POST
URL
https://p123trial-acc-space-deepinsertmulti-srv.../odata/v2/RelationService/CompanyEntity
Headers
Content-Type: application/json
Request body
{
"companyId": 1,
"companyName": "PetShop",
"linkToContact_contactId": 11,
"linkToContact":
{
"contactId": 11,
"contactName": "Petty",
"contactPhone": 123456,
"linkToCommunication_communicationId": 111,
"linkToCommunication":
{
"communicationId": 111,
"socialMedia": "Facebook",
"webAddress": "www.facebook.com",
"linkToComment_commentId": 1111,
"linkToComment":
{
"commentId": 1111,
"message": "very nice"
}
}
}
}

Afterwards, I was able to view the created entities in the 4 respective collections
And I was able to test the navigation
https://trial-acc-space-deepinsertmulti-srv...Service/CompanyEntity(1)/linkToContact
https://trial-acc-space-deepinsertmulti-srv.../ContactEntity(11)/linkToCommunication
https://trial-acc-space-deepinsertmulti-srv.../CommunicationEntity(111)/linkToComment

And the $expand on all nested navigation links
...<srv>/CompanyEntity?$expand=linkToContact/linkToCommunication/linkToComment

The screenshot points you to the result with the 3 nested inline entries



Is it this what you wanted to do?

I hope I have answered your question and it will help you with your endeavors
It has been interesting for me to try it out
BTW, you could have tried it yourself… ?

I have to come to an end, as I’m running out of paper.
I wish you a nice and relaxing evening,
Have a nice time and good health for you and your beloved ones.
Good luck with all your requests
PS and good luck with CAP
PS and keep writing friendly comments…?

Cheers,
Carlos




Attachments: Project Files


data-model.cds
namespace com.relation;

entity CompanyEntity {
key companyId : Integer;
companyName : String;
linkToContact : Association to ContactEntity;
}

entity ContactEntity {
key contactId : Integer;
contactName : String;
contactPhone : Integer;
linkToCommunication : Association to CommunicationEntity;
}

entity CommunicationEntity {
key communicationId : Integer;
socialMedia : String;
webAddress : String;
linkToComment : Association to CommentEntity;
}

entity CommentEntity {
key commentId : Integer;
message : String;
}

cat-service.cds
using com.relation from '../db/data-model';

service RelationService {
entity CompanyEntity as projection on relation.CompanyEntity
entity ContactEntity as projection on relation.ContactEntity;
entity CommunicationEntity as projection on relation.CommunicationEntity;
entity CommentEntity as projection on relation.CommentEntity;
}

ServiceImplementation.java
package com.example;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sap.cloud.sdk.service.prov.api.EntityData;
import com.sap.cloud.sdk.service.prov.api.ExtensionHelper;
import com.sap.cloud.sdk.service.prov.api.exception.DatasourceException;
import com.sap.cloud.sdk.service.prov.api.operations.Create;
import com.sap.cloud.sdk.service.prov.api.request.CreateRequest;
import com.sap.cloud.sdk.service.prov.api.response.CreateResponse;

public class ServiceImplementation {

@Create(entity = "CompanyEntity", serviceName = "RelationService")
public CreateResponse createCompany(CreateRequest createRequest, ExtensionHelper extensionHelper) throws DatasourceException{
// 1) retrieve the request payload, the data to create in backend
Map<String, Object> mapForCreation = createRequest.getData().asMap();

// 2) create map for each entity of deep insert: map key field to entity / resp. map key field to association
Map<String, List<String>> keyMap = new HashMap<String, List<String>>();
// Parent entity: CompanyEntity. Here, the key field is "companyId"
keyMap.put("CompanyEntity", Collections.singletonList("companyId"));
// For nested entity: assign the key field (contactId) of navigation target entity (ContactEntity) to the navigationProperty name (linkToContact)
keyMap.put("linkToContact", Collections.singletonList("contactId"));
// multi-level deep insert: continue navigation from ContactEntity to CommunicationEntity
keyMap.put("linkToCommunication", Collections.singletonList("communicationId"));
// multi-level deep insert: continue navigation from CommunicationEntity to CommentEntity
keyMap.put("linkToComment", Collections.singletonList("commentId"));

// 3) send data to database, including the info about keys
EntityData entityDataToCreate = EntityData.createFromDeepMap(mapForCreation, keyMap, "RelationService.CompanyEntity");
// execute it in database
EntityData result = extensionHelper.getHandler().executeInsertWithAssociations(entityDataToCreate, true);
return CreateResponse.setSuccess().setData(result).response();
}
}

 

 

mta.yaml

(to be used in trial account)
_schema-version: 2.0.0
ID: DeepInsertMulti
version: 1.0.0
modules:
- name: DeepInsertMulti-db
type: hdb
path: db
parameters:
memory: 256M
disk-quota: 256M
requires:
- name: DeepInsertMulti-db-hdi-container
- name: DeepInsertMulti-srv
type: java
path: srv
parameters:
memory: 990M
provides:
- name: srv_api
properties:
url: ${default-url}
requires:
- name: DeepInsertMulti-db-hdi-container
properties:
JBP_CONFIG_RESOURCE_CONFIGURATION: '[tomcat/webapps/ROOT/META-INF/context.xml:
{"service_name_for_DefaultDB" : "~{hdi-container-name}"}]'
- name: DeepInsertMulti-uaa
resources:
- name: DeepInsertMulti-db-hdi-container
type: com.sap.xs.hdi-container
properties:
hdi-container-name: ${service-name}
- name: DeepInsertMulti-uaa
type: org.cloudfoundry.managed-service
parameters:
service-plan: application
service: xsuaa
config:
xsappname: DeepInsertMulti-${space}
tenant-mode: dedicated