Spring Boot 如何使用Sping Boot Boot使用JPA和Specifications查找多个动态值

mwecs4sa  于 7个月前  发布在  Spring
关注(0)|答案(1)|浏览(73)

我正在使用Sring Boot ,我有一个实体Product,它有一个Map<String,String>表示产品的属性。我想做一个控制器,允许用户发送一个属性列表,每个属性的比较运算符,然后找到满足条件的产品。
我试着做了以下几件事:
这是我的实体

@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @ElementCollection
    @MapKeyColumn(name="name")
    @Column(name="value")
    private Map<String,String> attributes;
}

字符串
然后我使用searchCriteria来定义我要搜索的属性

public class SearchCriteria {
    private String key;
    private String operation;
    private String value;
}


最后,我的规范,现在只找到一个单一的属性,但这是不工作的一部分,因为以下错误:java.lang.IllegalStateException: Basic paths cannot be dereferenced

public class ProductSpecification implements Specification<Product>{

    private SearchCriteria searchCriteria;

    public ProductSpecification(SearchCriteria searchCriteria) {
        this.searchCriteria = searchCriteria;
    }

    @Override
    public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
        String operation = searchCriteria.getOperation();
        switch (operation) {
            case "==":
                return criteriaBuilder.equal(root.join("attributes").get(searchCriteria.getKey()),searchCriteria.getValue());      
            case "<":
                return criteriaBuilder.lessThan(root.join("attributes").get(searchCriteria.getKey()),searchCriteria.getValue());
            case ">":
                return criteriaBuilder.greaterThan(root.join("attributes").get(searchCriteria.getKey()),searchCriteria.getValue());
            default:
                return null;
        }
    }
}

x

@Service
public class ProductService {

    @Autowired
    ProductRepository productRepository;

    public List<Product> findBy(SearchCriteria searchCriteria){
        ProductSpecification productSpecification = new ProductSpecification(searchCriteria);
        return productRepository.findAll(productSpecification);
    }
@Controller
@RequestMapping("/api/product")
public class ProductController {

    @Autowired
    ProductService productService;

    @GetMapping("findBy")
    public ResponseEntity<?> findBy(@RequestBody SearchCriteria searchCriteria){
        List<Product> products = productService.findBy(searchCriteria);
        return new ResponseEntity<>(products, HttpStatus.OK);
    }

的一种或多种

xv8emn3q

xv8emn3q1#

最后,我用下面的方法解决了这个问题。

@Override
public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
    String operation = searchCriteria.getOperation();
    MapJoin<Product,String, String> attributesJoin = root.joinMap("attributes"); 

    switch (operation) {
        case "==":
            Predicate predicateKey = criteriaBuilder.equal(attributesJoin.key(), searchCriteria.getKey());
            Predicate predicateValue = criteriaBuilder.equal(attributesJoin.value(), searchCriteria.getValue());
            return criteriaBuilder.and(predicateKey,predicateValue);

字符串

相关问题