首页 > 解决方案 > 通过 id 限制搜索

问题描述

我想实现一个端点,用于搜索受 class_id 限制的表:

桌子:

    @Entity
    @Table(name = "class_items")
    public class ClassItems implements Serializable {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id", unique = true, updatable = false, nullable = false)
        private int id;
    
        @Column(name = "class_id", length = 20)
        private Integer classId;
    
        @Column(name = "title", length = 75)
        private String title;
    }

    @PostMapping("/{class_id}/find")
    public Page<ClassCategoriesFullDTO> search(@PathVariable("class_id") Integer classId, @Valid ClassCategoriesSearchParams params, Pageable pageable) {

        Page<ClassCategoriesFullDTO> list = classItemsRestService.findClassItemsByClassId(classId, params, pageable);
        return list;
    }

public Page<ClassCategoriesFullDTO> findClassItemsByClassId(Integer classId, ClassCategoriesSearchParams params, Pageable pageable) {

        // Limit here queries by classId

        Specification<Product> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (params.getTitle() != null) {
                predicates.add(cb.equal(root.get("title"), params.getTitle()));
            }           
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        return classItemsService.findAllByClassId(spec, pageable).map(classItemsMapper::toFullDTO);
    }

@Service
@Transactional
public class ClassItemsServiceImpl implements ClassItemsService {
    @PersistenceContext
    private EntityManager entityManager;
    private ClassItemsRepository dao;

    @Autowired
    public ClassItemsServiceImpl(ClassItemsRepository dao) {
        this.dao = dao;
    }

    public Page<ClassItems> findAllByClassId(Specification spec, Pageable pageable) {
        return this.dao.findAllByClassId(spec, pageable);
    }
}


@Repository
public interface ClassItemsRepository extends JpaRepository<ClassItems, Long>, JpaSpecificationExecutor<ClassItems> {

    Page<ClassItems> findAllByClassId(Specification spec, Pageable pageable);
}

我得到错误:

参数值[org.service.ClassItemsRestServiceImpl$$Lambda$1987/0x0000000801e21440@3c4de5a9] did not match expected type [java.lang.Integer (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [org.service.ClassItemsRestServiceImpl$$Lambda$1987/0x0000000801e21440@3c4de5a9] did not match expected type [java.lang.Integer (n/a)]",

你知道我该如何解决这个问题吗?

标签: springspring-bootspring-data-jpaspring-data

解决方案


您收到此错误是因为 Spring Data 正在尝试基于方法 name 生成查询findAllByClassId,因此它需要一个整数作为第一个参数。

使用规范时,您应该使用JpaSpecificationExecutor. 添加您自己的带有规范的方法作为参数是行不通的。如果要过滤classId,请将适当的过滤器附加到规范本身。

编辑解决方案是在构建规范时添加额外的条件:

Specification<Product> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (params.getTitle() != null) {
                predicates.add(cb.equal(root.get("title"), params.getTitle()));
            }
            predicates.add(cb.equal(root.get("classId"), classId));           
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

然后,在 中ClassItemsServiceImpl,调用dao.findAll(spec)


推荐阅读