【问题标题】:Handling Optional get method inside Services在服务中处理可选的 get 方法
【发布时间】:2022-01-05 14:47:27
【问题描述】:

我正在实现一个 API,但在我的服务层我真的不知道如何处理 Optionals 的 .get()

@Service
public class AttributedValueService {
    ...

    public AttributedValueDTO createAttributedValue(ActionDTO actionDTO) {
        Optional<RedeemableValue> redeemableValue = redeemableValueRepository.findRedeemableValueByProductId(actionDTO.getProductId());
        Optional<Value> value = valueRepository.findById(redeemableValue.get().getValue().getId());
        AttributedValue attributedValue = new AttributedValue(value.get(), actionDTO.getId(), actionDTO.getUserId());
        return new AttributedValueDTO(attributedValueRepository.save(attributedValue));
    }
}

我的 API 接收一个对象并使用来自该对象的信息从数据库中检索一些其他对象,我想确保当 .get() 之一找不到对象时返回 ObjectNotFound

目前我正在考虑在 find 调用中使用orElseThrow,类似这样:

@Service
public class AttributedValueService {
    ...

    public AttributedValueDTO createAttributedValue(ActionDTO actionDTO) {
        RedeemableValue redeemableValue = redeemableValueRepository.findRedeemableValueByProductId(actionDTO.getProductId())
        .orElseThrow(() -> new ObjectNotFoundException("Id: "+redeemableValueDTO.getRedeemableValueId(),"Referred Redeemable Value could not be found"));

        Value value = valueRepository.findById(redeemableValue.get().getValue().getId())
        .orElseThrow(() -> new ObjectNotFoundException("Id: "+valueDTO.getValueId(),"Referred Value could not be found"));

        AttributedValue attributedValue = new AttributedValue(value.get(), actionDTO.getId(), actionDTO.getUserId());
        return new AttributedValueDTO(attributedValueRepository.save(attributedValue));
    }
}

为 Spring 留下异常处理,返回 404。但是,这是正确的方法吗?

编辑: 修复了 createAttributedValue 方法的可选返回,感谢提示。

【问题讨论】:

  • 没有“灵丹妙药”,不同的团队可能会以不同的方式解决这个问题。我认为您的方法没有任何本质上的错误。
  • 尽管返回 Optional&lt;AttributedValueDTO&gt; 有点误导,因为在建议的流程中没有执行会返回空的可选项。你要么返回一个实际的对象,要么抛出一个异常。
  • 我宁愿使用 JSR-305 @Nullable 或自定义包级别@NonnullByDefault 而不是使用 Optional 假装存在“NPE 安全”(没有不必要的 Optional 框,闭包限制,完整的“可能是可选的,绝对永远不会为空,但仍然是可选的”一致性等)。

标签: java spring service optional


【解决方案1】:

首先,正如@Turing85 所说,没有灵丹妙药

如果你有 RedeemableValueServiceValueService 你可以让这些类处理 Optional 而不是在 AttributedValueService em>

应该是这样的:

@Service
public class AttributedValueService {
    ...

    public AttributedValueDTO createAttributedValue(ActionDTO actionDTO) {
        Value value = valueService.findByProductId(actionDTO.getProductId());
        AttributedValue attributedValue = new AttributedValue(value, actionDTO.getId(), actionDTO.getUserId());
        return new AttributedValueDTO(attributedValueRepository.save(attributedValue));
    }
}

@Service
public class ValueService {
    ...

    public Value findByProductId(IdType productId) {
        RedeemableValue redeemableValue = redeemableValueService.findByProductId(productId);
        return valueRepository.findById(redeemableValue.getValue().getId()).orElseThrow(YourException::new);
    }
}

@Service
public class RedeemableValueService {
    ...

    public RedeemableValue findByProductId(IdType productId) {
        return redeemableValueRepository.findRedeemableValueByProductId(productId).orElseThrow(YourException::new);
    }
}

【讨论】:

    【解决方案2】:

    如果我猜对了,那么你只有用例:

    • 要么一无所获,就会抛出异常
    • 或者你找到了一些东西,然后你返回这个对象

    因此不需要 Optional 因为它永远不会缺席^^ 那么为什么要增加这种复杂性呢?

    【讨论】:

      【解决方案3】:

      据我了解您的问题,您的要求是检查您从数据库中获取的对象是否存在,如果不存在,那么您想抛出一些异常。 在 Optional 类中,我们有一个方法 isPresent() 如果 Optional 有某个值则返回 true,否则返回 false。

      你可以这样做:

      @Service
      public class AttributedValueService {
          ...
      
          public Optional<AttributedValueDTO> createAttributedValue(ActionDTO actionDTO) {
              Optional<RedeemableValue> redeemableValue = redeemableValueRepository.findRedeemableValueByProductId(actionDTO.getProductId());
      if(redeemableValue.isPresent()){
              Optional<Value> value = valueRepository.findById(redeemableValue.get().getValue().getId());
      if(value.isPresent()){
              AttributedValue attributedValue = new AttributedValue(value.get(), actionDTO.getId(), actionDTO.getUserId());
              return Optional.of(new AttributedValueDTO(attributedValueRepository.save(attributedValue)));}
      else{
      throw ObjectNotFoundException() //  custom exception
      }
      }
      else{
      throw ObjectNotFoundException() //  custom exception
      }
          }
      }
      

      我不明白您返回 Optional 背后的逻辑,因为在每一步我们都在检查可选值,然后就不需要了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多