如何使用标准构建器使用多个过滤器进行搜索

Posted

技术标签:

【中文标题】如何使用标准构建器使用多个过滤器进行搜索【英文标题】:How to search with multiple filter using criteria builder 【发布时间】:2019-12-24 11:55:44 【问题描述】:

我想用java做一个多重过滤器,我用的是Spring Boot。我的查询是使用标准编写的。

SearchApp.java:

@Entity
@Table(name = "searchapp")
public class SearchApp implements Serializable 

@Column(name = "code")
private String code;
@Column(name = "release")
private String release;
@Column(name = "environnement")
private String environnement;
@Column(name = "date")
private Date date;
private static final long serialVersionUID = -1701849052760947052L;

public SearchApp() 
    super();
    // TODO Auto-generated constructor stub

public DeploiementApp(String code, String release, String environnement, Date date) 
    super();
    this.code = code.toLowerCase();
    this.release = release;
    this.environnement = environnement;
    this.date= date;    

我有一个搜索控制器,这是进入我的应用程序的大门

SearchController.java:

@Autowired
SearchService searchService;

@GetMapping("/filtersearch")
public List<SearchApp> filter(@RequestParam("code") String code, @RequestParam("release") String release, @RequestParam("environnement") String environnement, @RequestParam("date") String date) 

    return searchService.filter(code.toUpperCase(), release.toUpperCase(), environnement.toUpperCase(), date);

SearchService.java:

List<SearchApp> filter(String code, String environnement, String release, String date);

SearchServiceImpl.java:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;

public SearchServiceImpl(EntityManager em) 
    super();
    this.em = em;


@Override
public List<SearchApp> filter(String code, String release, String environnement, String date) 


    DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    format.setTimeZone(TimeZone.getTimeZone("Europe/Paris"));
    Date dateBD = new Date();
         dateBD = format.parse(date);
     catch (ParseException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    
    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    //select
    CriteriaQuery<SearchApp> criteriaQuery = criteriaBuilder.createQuery(SearchApp.class);
    //from
    Root<SearchApp> itemRoot = criteriaQuery.from(SearchApp.class);
    // attribut

    List<Predicate> predicate = new ArrayList<Predicate>();

    if(  code != "" || code != null) 
        Predicate predicateCode = criteriaBuilder.equal(itemRoot.get("code"), code);
        predicate.add(predicateCode);
    

    if(  release != "" || release != null) 
        Predicate predicateRelease = criteriaBuilder.equal(itemRoot.get("release"), release);
        predicate.add(predicateRelease);
    

    if(  environnement != "" || environnement != null) 
        Predicate predicateEnvironnement = criteriaBuilder.equal(itemRoot.get("environnement"), environnement);
        predicate.add(predicateEnvironnement);
    

    if(  dateBD != null ) 
        Predicate predicateDate = criteriaBuilder.equal(itemRoot.get("date"), date);
        predicate.add(predicateDate);
    

    Predicate And = criteriaBuilder.and(predicate.toArray(new Predicate[predicate.size()]));

    //where
    criteriaQuery.where(And);
    List<SearchApp> result = em.createQuery(criteriaQuery).getResultList();

    return result;

它不起作用。

错误:org.hibernate.query.criteria.internal.predicate.ComparisonPredicate@41f4f353 org.hibernate.query.criteria.internal.predicate.ComparisonPredicate@77ef22f7 还有日期错误

【问题讨论】:

首先你应该改变 ||与你的 if 空支票 &&。我也倾向于使用 isEmpty() docs.oracle.com/javase/7/docs/api/java/lang/… - 然后不是那样。 谓词 predicateDate = criteriaBuilder.equal(itemRoot.get("date"), date); value 应该是 dateBD 而不是 date。 比较好但是效果不好 分享你得到的最新异常 没有更多异常,但预期的结果并不好 【参考方案1】:

在使用 toUpperCase() 时将值直接传递给服务层,如果值为 null 并且在服务层检查 null 后,在标准构建器中使用 upper,例如,

"criteriaBuilder.equal(criteriaBuilder.upper(itemRoot.get("code"), code.toUpperCase());"

使用 dateDB 代替日期,字符串日期应解析为 Date 对象。希望它能解决您的问题。 @Column(名称 = "日期") 私人日期日期; 日期列应为数据库表中的日期。

【讨论】:

感谢您的回答,这解决了我的部分问题,我的日期问题仍然明显链接到我的数据库。 日期不依赖于数据库,我们可以简单地匹配日期。 我们也可以使用如下谓词 predicates.add(criteriaBuilder.equal(itemRoot.get(date), dateBD));

以上是关于如何使用标准构建器使用多个过滤器进行搜索的主要内容,如果未能解决你的问题,请参考以下文章

JPA CriteriaBuilder - 如何使用“IN”比较运算符

如何使用过滤器按钮构建重叠搜索栏

微软搜索使用多个标准(通配符,排除等)

如何使用 ag-grid 自定义过滤器组件构建查找搜索功能

如何在 AppSync 解析器中使用多个过滤器表达式

如何使用 isotope.js 制作具有多个 slectbox 的搜索过滤器?