如何通过oData创建新的子节点实体而不更新或创建根节点

时间:2018-08-07 07:02:25

标签: java s4sdk

我在S / 4HANA Cloud中创建了一个自定义业务对象,它包含一个父节点和一个子节点,还为S / 4HANA自定义OData服务生成了Java VDM。我将其与SAP Cloud Platform SDK结合在一起用于服务开发(我现在无法找到其“ SAP帮助”页面)。

该方案是只需将新的子节点添加到现有的根节点。

当我尝试使用其他字段值对ParentEntitySet()/ childNavigation进行POST操作时,收到错误消息“无效的方法调用:在非根实体YY1_CHILD_ENTITY上调用了“ CREATE”方法。

我该怎么办才能解决此错误?

更新:

旧代码导致了我所描述的错误

@Create(serviceName = "CrudService", entity = "ChildEntitySet", sourceEntity = "ParentEntitySet")
    public CreateResponse createABC(CreateRequest createRequest) {

        EntityData entity = createRequest.getData();

        LeaveRequest response;
        try {
            response = new CreateChildCommand(new ErpConfigContext(), new DefaultService(), entity)
                    .execute();
        } catch (HystrixBadRequestException e) {
            return CreateResponse.setError(new ErrorResponseImpl(400, null, e.getMessage(), e.getCause(), null));
        }

        CreateResponse readResponse = CreateResponse.setSuccess().setData(response).response();

        return readResponse;
    }

新代码:当我尝试通过导航发布子实体时,错误消失了,但是出现了新错误。

Inavalid Entity name: No entity with name ParentClass(guid'<parentKey>')/to_ChildEntity in the OData service

但是,当我使用与上面相同的url进行导航查询时,它运行良好。仅使用导航创建会出现此问题。

@Create(serviceName = "CrudService", entity = "ChildEntitySet", sourceEntity = "ParentEntitySet")
    public CreateResponse createChild(CreateRequest createRequest) {

        EntityData entity = createRequest.getData();

        String parentKey = (String) createRequest.getSourceKeys().get(<parentKey>);

        ChildClass response = new ChildClass();
        Map<String, Object> childEntity = new HashMap<>();
        try {
            childEntity = entity.asMap();
            response.setParentKey((String) entity.asMap().get(<parentKey>));
            response.setText((String) entity.asMap().get("Text"));
            response.setCreatedBy((String) entity.asMap().get("CreatedBy"));
            response.setCreatedOn((Calendar) entity.asMap().get("CreatedOn"));

            ParentClass parent = new ParentReadByKeyCommand(new ErpConfigContext(), parentKey)
                    .execute();
            parent.createChildEntity(childEntity);
            return CreateResponse.setSuccess().setData(response).response();
        } catch (Exception e) {
            // Return an instance of QueryResponse containing the error in case of failure
            ErrorResponse errorResponse = ErrorResponse.getBuilder().setMessage(e.getMessage())
                    .setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR).setCause(e).response();
            return CreateResponse.setError(errorResponse);
        }
    }

以下方法属于ParentClass

public ChildClass createChildEntity(Map<String, Object> childEntity) throws ODataException {
        if (erpConfigContext == null) {
            throw new ODataException(ODataExceptionType.OTHER, "Failed to fetch related objects of type ChildClass.",
                    new IllegalStateException(
                            "Unable to execute OData query. The entity was created locally without an assigned ERP configuration context. This method is applicable only on entities which were retrieved or created using the OData VDM."));
        }
        final StringBuilder odataResourceUrl = new StringBuilder(getEntityCollection());
        odataResourceUrl.append("(");
        odataResourceUrl.append(ODataTypeValueSerializer.of(EdmSimpleTypeKind.Guid).toUri(<parentKey>));
        odataResourceUrl.append(")/");
        odataResourceUrl.append("to_ChildEntity");
        final ODataCreateRequestBuilder builder = ODataCreateRequestBuilder
                .withEntity(getEndpointUrl(), odataResourceUrl.toString()).withBodyAsMap(childEntity);
        final ODataCreateRequest query = builder.build();
        final ODataCreateResult result = query.execute(erpConfigContext);
        final ChildClass entity = result.as(ChildClass.class);
        entity.setErpConfigContext(erpConfigContext);
        return entity;
    }

我正在使用

<parent>
        <groupId>com.sap.cloud.servicesdk.prov</groupId>
        <artifactId>projects-parent</artifactId>
        <version>1.19.0</version>
    </parent>

<dependencies>
        <dependency>
            <groupId>com.sap.cloud.s4hana</groupId>
            <artifactId>sdk-parent</artifactId>
            <version>1.11.1</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.sap.cloud.s4hana</groupId>
            <artifactId>s4hana-all</artifactId>
            <!-- <version>1.11.1</version> -->
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

1 个答案:

答案 0 :(得分:4)

某些OData API仅允许通过根实体创建子实体。

但是,当前,S / 4HANA Cloud SDK的VDM不支持此功能。

如果有更新,我将更新此答案。

更新: 从2.4.1版开始,如果使用S / 4 HANA Cloud SDK,则现在可以将实体创建为另一个实体的子代。

代码可能看起来像这样:

new YourCustomService()
    .createChildEntity(childEntity)
    .asChildOf(parentEntity, ParentEntity.TO_CHILD_ENTITY)
    .execute();

或者使用SDK提供的BusinessPartner的更实际的示例:

new DefaultBusinessPartnerService().createBusinessPartnerAddress(someAddress)
    .asChildOf(
        someBusinessPartner,
        BusinessPartner.TO_BUSINESS_PARTNER_ADDRESS
    )
    .execute();