我正在项目中更新对Spring 5的依赖关系,并遭到编译错误的轰炸,其中findOne()
的方法定义已由findById()
替换,现在返回了Optional
(正确如果我错了我。
在重构的过程中,我遇到了多种可以选择采用的方法,因此,我希望有一些输入是首选的。
第一种方法:
ExpectedPackage ep = expectedPackageRepository.findById(1).orElse(null);
if(ep != null){
ep.setDateModified(new Date());
expectedPackageRepository.saveAndFlush(ep);
}
第二种方法:
Optional<ExpectedPackage> ep = expectedPackageRepository.findById(1);
if(ep.isPresent()){
ep.get().setDateModified(new Date());
expectedPackageRepository.saveAndFlush(ep.get());
}
还是我错过了第三种更好的方法?我经历了几个问题和几篇文章,但没有找到明确的答案。
答案 0 :(得分:19)
您也可以这样做:
expectedPackageRepository.findById(1).ifPresent(
ep -> {
ep.setDateModified(new Date());
expectedPackageRepository.saveAndFlush(ep);
}
);
理想情况下,您还可以将方括号({}
)之间的部分提取为单独的方法。然后,您可以这样写:
expectedPackageRepository.findById(1).ifPresent(this::doSomethingWithEp);
位置:
void doSomethingWithEp(ExpectedPackage ep) {
ep.setDateModified(new Date());
expectedPackageRepository.saveAndFlush(ep);
}
您可以在此处阅读ifPresent
的文档:https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#ifPresent-java.util.function.Consumer-
如状态所示,如果存在该值,它将执行指定的操作,否则不执行任何操作。
答案 1 :(得分:6)
另一个答案基本上是对第二种方法的某种重构,本质上没有错,这只是样式问题。当然,链接和提取到一个单独的方法将使它更易读和清楚(毫无疑问(我是+1)),尤其是因为正确使用了ifPresent
。
我只是在这里补充说,get
被认为是某种设计错误(或者可能是错误的方法名称,可能来自guava
思维定势)。即使在get
被记录为在缺少该值时抛出异常的情况下,使用它也是有点怪异的(如果您认为这里的吸气剂,您不会指望getter
会抛出异常)。而且,您不会期望get
在之后 isPresent
之后被调用,至少在与Optional
的最初交互中不需要。因此,建议get
被弃用(并希望删除),因此java-10添加了一个更好的添加项orElseThrow()
-在您读完之后就很有意义了,因为抛出部分是以方法,所以没有惊喜。
另外,有人应该告诉您new Date()
的用法,当它与java-8中的Optional
一起使用时看起来很奇怪,已经有更好的与时间/日期相关的类了。
我也不太确定为什么在有PreUpdate/PrePersist
之类的春季注释时,为什么要手动更新修改日期。
答案 2 :(得分:5)
是的,还有其他方法。
如果您绝对希望始终有一个值,那么如果出现空值,则使用Optional::orElseThrow
引发异常。
如果您期望null可能到达,并且可以使用备用实例作为后备选项,请使用Optional::orElse
。
如果没有备用实例,但是您可以调用一个函数来提供备用实例,请使用Optional::orElseGet
。
如果您不希望收到空值,并且不想在空值到达时采取任何措施,请使用Optional::ifPresent
。如果值到达,则传递要运行的代码块。
如果您只关心到达的值是否满足某些要求,请使用Optional::filter
。通过Predicate
定义您的要求。例如,我们仅关心Optional< String >
包含文本且其中文本中包含单词purple
的情况:myOptional.filter( s -> s.contains( "purple" ) ).ifPresent( this::print ) ;
。如果收到null,则永远不会发生我们所需的操作(在此示例中为print
的调用)。如果接收到一个值但不满足我们的谓词,则我们期望的操作将永远不会发生。
执行if( myOptional.isPresent() ) { SomeClass x = myOptional.get() ; … }
是有效且安全的。但这不是Optional
的初衷,因为它与进行老式的空检查if ( null == x ) { … }
基本相同。 Optional
上的其他方法提供了一种更清晰,更优雅的方式来表达您对可能到达null的意图。
答案 3 :(得分:1)
您也可以这样做:
Optional<ExpectedPackage> updatedPackage = expectedPackageRepository.findById(1).map(ep -> {
ep.setDateModified(new Date());
return expectedPackageRepository.saveAndFlush(ep);
});