为什么 Hybris modelService.save() 在 ifPresent() 方法中不起作用?

Why Hybris modelService.save() doesn't work inside the ifPresent() method?

    private void doSomething(someProcessModel process){
        CustomerModel customer = process.getCustomerModel();

        customer.getFoos().stream()
                .filter(foo -> foo.getCountryCode().equals(process.getCountryCode()))
                .findFirst()
                .ifPresent(foo -> {
                    if(foo.getSomeNumber() == null){
                        foo.setSomeNumber("1234567");
                        modelService.save(foo);
                    }
                });
    }

如上面的代码片段所示,我有一个具有属性 'Foos' 的 'CustomerModel'。这是一对多的关系。如您所见,我做了一些过滤,最后,如果 'Foo' 的 'someNumber' 属性为空,我想更新它的值。我已确认一切正常,因为 "someNumber" 属性的值在调试期间已更新。它根本没有保存,因为我已经在 HMC 中完成了检查。我还验证了拦截器没有任何会引发错误的条件。日志中也没有显示任何内容。

我想知道在 'ifPresent()' 方法中执行“modelService.save()”是否合法?这里可能存在什么问题?

您必须谨慎对待模型中的列表,因为它们是不可变的,您必须设置整个新列表。此外,您仅在特定模型上调用了保存,这会更改其 Jalo 引用,这就是您的列表未更新的原因。改变流并在最后收集它会创建新列表,这就是为什么您可以直接从模型流式传输列表的原因。

private void doSomething(someProcessModel process){
    CustomerModel customer = process.getCustomerModel();
    ArrayList<FooModel> foos = doSomethingOnFoos(customer.getFoos());
    customer.setFoos(foos);
    modelService.saveAll(foos, customer);
}

//compare the value you know exists with something that might be NULL as equals can handle that, but not the other way around
private ArrayList<FooModel> doSomethingOnFoos(ArrayList<FooModel> fooList) {
     return fooList.stream()
                .filter(Objects::nonNull)
                .filter(foo -> process.getCountryCode().equals(foo.getCountryCode()))
                .filter(foo -> Objects.isNull(foo.getSomeNumber()))
                .map(foo -> foo.setSomeNumber(1234))
                .collect(toList());
}

我现在找到了根本原因,因为我又遇到了同样的问题。

我原来问题的背景

为了给我的原始问题提供更多上下文,#doSomething 方法驻留在 Hybris 业务流程操作中 class 并且我在调试它时过早地结束了操作(通过停止调试)一旦#doSomething 方法是 运行.

根本原因

上述问题发生在我调试动作class时。我假设一旦 ModelService#save 成为 运行,它将保持业务流程的当前状态。但是,如果有任何错误,Hybris OOTB 业务流程将执行回滚(我相信这是由我停止调试引起的half-way)。

SAP Commerce Documentation:

All actions are performed inside their own transaction. This means that changes made inside the action bean run method are rolled back in case of an error.

解决方案

让动作跑完全程!

很高兴知道

根据 SAP 文档和此 博客 post,有时我们需要绕过业务流程回滚,即使存在异常抛出并且有办法实现这一点。可以在这个 SAP Commerce Documentation 和提到的博客 post.

中找到更多信息

However, in some circumstances it may be required to let a business exception reach the outside but also commit the transaction and deal with the exception outside. Therefore, it is possible to make the task engine not roll back the changes made during a task which failed.