2

我在 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>
4

1 回答 1

0

一些 OData API 只允许通过根实体创建子实体。

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

如果有更新,我会更新这个答案。

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

代码可能如下所示:

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();
于 2018-08-07T13:32:18.963 回答