系统后台的列表页通常都有查询功能,如果通过写sql语句进行查询非常费时,特别是在查询条件较多的情况下。如果查询条件发生变化,则需要修改sql语句,非常麻烦。
jspxcms使用页面动态查询来解决这个问题,直接解析查询表单的名称来生成sql查询条件,只要修改页面就可以实现查询,而不需要修改java代码和写sql语句。
/WEB-INF/views/plug/resume/resume_list.jsp
(已做简化):
<form action="list.do" method="get">
名称:<input type="text" name="search_CONTAIN_name" value="${search_CONTAIN_name[0]}"/>
职位:<input type="text" name="search_CONTAIN_post" value="${search_CONTAIN_post[0]}"/>
开始日期:<input type="text" name="search_GTE_creationDate_Date" value="${search_GTE_creationDate_Date[0]}"/>
结束日期:<input type="text" name="search_LTE_creationDate_Date" value="${search_LTE_creationDate_Date[0]}" />
<button type="submit">搜索</button>
</form>
com.jspxcms.plug.domain.Resume;
public class Resume {
private Integer id;
private Site site;
private String name;
private String post;
private Date creationDate;
private String gender;
private Date birthDate;
private String mobile;
private String email;
...
}
其中 search_CONTAIN_name
search_CONTAIN_post
search_GTE_creationDate_Date
search_LTE_creationDate_Date
是关键内容。
search_
是前缀,代表这个输入框用于构建搜索条件。CONTAIN
GTE
LTE
是查询关键字。相当于 like
>=
<=
。name
post
creationDate
是查询的字段。是com.jspxcms.plug.domain.Resume
实体类中的属性名。_Date
是类型后缀,默认是字符串,所以字符串不需要类型后缀;creationDate是日期,所以要加上_Date
后缀。最后的效果类似 where name like '%abc%' and post like '%def%' and creationDate >= 'xxxx-xx-xx' and creationDate <= 'xxxx-xx-xx'
点击查询按钮后,希望把之前的查询条件值依然保留在页面上。
value="${search_CONTAIN_name[0]}"
的作用是将查询条件反填至页面,也就是点击查询按钮得到查询结果后,查询条件值依然显示在页面上,而不会变成空白。
如果name里面的值带有.
号,则必须使用这种格式:
name="search_CONTAIN_detail.title" value="${requestScope['search_CONTAIN_detail.title'][0]}"
上面的例子是只查询当前实体类的字段。
查询many-to-one或one-to-one的关联实体类的字段用.
分隔。比如search_CONTAIN_site.name
。
查询many-to-many或one-to-many的关联实体类的字段需加上J
前缀。比如Info查询中的search_CONTAIN_JinfoSpecials.Jspecial.title
search_CONTAIN_JinfoTags.Jtag.name
=
。like
。like
,且会在查询内容前后加上通配符,如 like '%abc%'
。like
,且会在查询内容后加上通配符,如 like 'abc%'
。like
,且会在查询内容后前上通配符,如 like '%abc'
。>
。<
。>=
。<=
。in
。package com.jspxcms.plug.web.back;
public class ResumeController {
@RequiresPermissions("plug:resume:list")
@RequestMapping("list.do")
public String list(@PageableDefault(sort = "id", direction = Direction.DESC) Pageable pageable,
HttpServletRequest request, org.springframework.ui.Model modelMap) {
Integer siteId = Context.getCurrentSiteId();
// 获取`search_`开头的查询字段
Map<String, String[]> params = Servlets.getParamValuesMap(request, Constants.SEARCH_PREFIX);
Page<Resume> pagedList = service.findAll(siteId, params, pageable);
modelMap.addAttribute("pagedList", pagedList);
return "plug/resume/resume_list";
}
在Controller中需要获取search_
开头的查询参数:Map<String, String[]> params = Servlets.getParamValuesMap(request, Constants.SEARCH_PREFIX);
package com.jspxcms.plug.service.impl;
public class ResumeServiceImpl implements ResumeService, SiteDeleteListener {
public Page<Resume> findAll(Integer siteId, Map<String, String[]> params, Pageable pageable) {
return dao.findAll(spec(siteId, params), pageable);
}
private Specification<Resume> spec(final Integer siteId, Map<String, String[]> params) {
// 解析页面传递过来的params参数
Collection<SearchFilter> filters = SearchFilter.parse(params).values();
final Specification<Resume> fsp = SearchFilter.spec(filters, Resume.class);
Specification<Resume> sp = new Specification<Resume>() {
public Predicate toPredicate(Root<Resume> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// 此处可以增加额外查询条件。属于JPA的用法,具体请查看JPA文档。
Predicate pred = fsp.toPredicate(root, query, cb);
if (siteId != null) {
pred = cb.and(pred, cb.equal(root.get("site").<Integer>get("id"), siteId));
}
return pred;
}
};
return sp;
}
}
查询解析类: com.ujcms.common.orm.SearchFilter
。