我想在我的Repository中有一个返回单个值的方法。 像这样:
TrainingMode findByTrainingNameAndNameEng( String trainingName, String nameEng );
http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/
Spring Data Docs描述了在这种情况下,如果没有找到实体,该方法可以返回null。
我想抛出像No TrainingMode found by %trainingName% and %nameEng%
这样的通用消息或像这样的smth的异常。
我可以使用Optional<TrainingMode>
作为返回值,然后使用orElseThrow
Optional<TrainingMode> findByTrainingNameAndNameEng( String trainingName, String nameEng );
repository.findByTrainingNameAndNameEng(name, nameEng).orElseThrow(() -> new RuntimeException(...));
但每次调用此方法时都应该调用此方法。目前尚不清楚 - DRY原则已被打破。
如何使用Spring Data使用orElseThrow获取非空单值?
答案 0 :(得分:1)
如果在整个调用它的应用程序逻辑中复制空值处理,则会违反DRY原则。如果DRY原则是您最担心的事情,那么我可以想到:
您可以制作一个&#34;服务&#34;将调用委托给带注释的存储库并对其处理空响应逻辑的类,并使用该服务类而不是直接调用存储库。缺点是会为您的应用程序引入另一个层(这会将存储库与您的应用程序逻辑分离)。
有可能在您的数据存储库中添加自定义行为,这些行为在&#34; 3.6.1. Adding custom behavior to single repositories&#34;文档部分。很抱歉没有发布代码段。
我个人对第二种方法的问题是它污染了带有接口的app,强制你遵循某种命名模式(从不喜欢&#39; Impl&#39;后缀),并且可能会使代码迁移更多时间消费(当app变大时,跟踪哪个界面负责哪个自定义行为变得更难,然后人们只是简单地开始创建他们自己的行为,结果证明是另一个的重复)。
答案 1 :(得分:1)
我找到了解决方案。
首先,Spring Data处理getByName和findByName。我们可以使用它:在我的情况下,find *可以返回null(或者返回not null可选,如你所愿)和get *应该只返回值:如果返回null则抛出异常。
我决定在这种情况下使用AOP。 这是方面:
@Aspect
@Component
public class GetFromRepositoryAspect {
@Around("execution(public !void org.springframework.data.repository.Repository+.get*(..))")
public Object aroundDaoMethod( ProceedingJoinPoint joinpoint ) throws Throwable {
Object result = joinpoint.proceed();
if (null == result) {
throw new FormattedException( "No entity found with arhs %s",
Arrays.toString( joinpoint.getArgs() ) );
}
return result;
}
}
就是这样。
答案 2 :(得分:1)
您可以使用Spring nullability annotations来实现。如果方法的返回类型只是某些Entity而不是包装类型,例如Optional<T>
,则在无结果的情况下将抛出org.springframework.dao.EmptyResultDataAccessException
。