我有以下存储库:
@Repository
public interface EntityRepository extends JpaRepository<Entity, Long> {
List<Entity> findAllByFirstId(Long firstId);
List<Entity> findAllBySecondId(Long secondId);
List<Entity> findAllByFirstIdAndSecondId(Long firstId, Long secondId);
}实现用io.swagger:swagger-codegen-maven-plugin生成的接口的构造函数使用Optional<Long>作为可选的请求参数(底层服务也使用相同的参数):
ResponseEntity<List<Entity>> entities(Optional<Long> firstId, Optional<Long> secondId);我想根据参数firstId和secondId过滤实体,这些参数从来不是数据库中的null,但可以通过构造函数传递(用于搜索的参数是可选的)。
当传递null参数为可选参数时,命名查询会出现问题,JpaReposotory使用null作为数据库中搜索的标准。这就是我不想要的--只要是null,我就想忽略基于这个参数的过滤。
我基于Optional的解决方案是:
public List<Entity> entities(Optional<Long> firstId, Optional<Long> secondId) {
return firstId
.or(() -> secondId)
.map(value -> {
if (firstId.isEmpty()) {
return entityRepository.findAllBySecondId(value);
}
if (secondId.isEmpty()) {
return entityRepository.findAllByFirstId(value);
}
return entityRepository.findAllByFirstIdAndSecondId(
firstId.get(), secondId.get());
})
.orElse(entityRepository.findAll())
.stream()
.map(...) // Mapping between DTO and entity. For sake of brevity
// I used the same onject Entity for both controler and repository
// as long as it not related to the question
.collect(Collectors.toList());
}这个问题已经被问到了:Spring数据-如果参数为空值,则忽略参数和一张创建DATAJPA-209的票据。
只要这个问题已经存在了将近3年,并且票证可以追溯到2012年,我想问,是否有一种更舒适和更通用的方法来避免处理Optional和复制存储库方法的开销。对于两个这样的参数的解决方案看起来是可以接受的,但是我想对4-5参数实现相同的过滤。
发布于 2020-02-16 06:52:37
您需要像这样的Specification实用程序类
public class EntitySpecifications {
public static Specification<Entity> firstIdEquals(Optional<Long> firstId) {// or Long firstId. It is better to avoid Optional method parameters.
return (root, query, builder) ->
firstId.isPresent() ? // or firstId != null if you use Long method parameter
builder.equal(root.get("firstId"), firstId.get()) :
builder.conjunction(); // to ignore this clause
}
public static Specification<Entity> secondIdEquals(Optional<Long> secondId) {
return (root, query, builder) ->
secondId.isPresent() ?
builder.equal(root.get("secondId"), secondId.get()) :
builder.conjunction(); // to ignore this clause
}
}那么您的EntityRepository必须扩展JpaSpecificationExecutor
@Repository
public interface EntityRepository
extends JpaRepository<Entity, Long>, JpaSpecificationExecutor<Entity> {
}用法:
@Service
public class EntityService {
@Autowired
EntityRepository repository;
public List<Entity> getEntities(Optional<Long> firstId, Optional<Long> secondId) {
Specification<Entity> spec =
Specifications.where(EntitySpecifications.firstIdEquals(firstId)) //Spring Data JPA 2.0: use Specification.where
.and(EntitySpecifications.secondIdEquals(secondId));
return repository.findAll(spec);
}
}https://stackoverflow.com/questions/60243712
复制相似问题