序列化表单为json对象,datagrid带额外参提交一次查

来源:http://www.prospettivedarte.com 作者:计算机教程 人气:83 发布时间:2019-05-31
摘要: 查询窗口中可以设置很多查询条件 相信熟悉Hibernate的人对于ORM给编程带来的便利于快捷一定不陌生,相对于MyBatis等需要编写复杂的SQL语句,ORM映射为我们带来的便利显而易见。但是,

 查询窗口中可以设置很多查询条件

  相信熟悉Hibernate的人对于ORM给编程带来的便利于快捷一定不陌生,相对于MyBatis等需要编写复杂的SQL语句,ORM映射为我们带来的便利显而易见。但是,在获得便利的同时,失去的便是灵活性,这里不是说Hibernate不灵活,只是针对初学者来说,要掌握灵活的技巧,需要的成本相对较高。过去的半年里,在项目中通过Spring Cloud实现了一套关于为服务的基础架构,其中在数据持久层采用的是Spring Data JPA,对于曾经用过Hibernate的人来说,选择JPA会十分容易上手,因为语法一切都是那么熟悉。但是,在涉及到复杂的查询的时候,尤其是多条件查询的时候,如果通过命名方式实现,长长的方法名将是代码显得十分的不优雅。这个时候,大多数人会选择使用NativeQuery,通过编写SQL语句来实现,这种方式导致的结果就是项目代码中遍地是SQL,随着时间的推移,项目已经失去了使用JPA的初衷。能否有一种方式,在保障JPQL的风格里完成这种复杂的查询呢?这里介绍一种简单的方式:JpaSpecificationExecutor

表单中输入的内容转为datagrid的load方法所需的查询条件向原请求地址再次提出新的查询,将结果显示在datagrid中

  JpaSpecificationExecutor不属于JpaRepository体系,它允许自定义查询条件实现查询。通过源码可以发现,JpaSpecificationExecutor提供了如下几个方法:

转换方法看代码注释

  public interface JpaSpecificationExecutor<T> {

<td colspan="2"><a id="searchBtn" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-search'">查询</a> 
<script type="text/javascript">
    $("#searchBtn").click(function(){
        //1、将查询条件值获取到
        var condition = $("#searchForm").serializeJson();
        console.info(condition);
        //2、带参提交一次查询,从服务器加载新数据 包括两种数据1、分页需要page,rows 2、查询条件
        $('#grid').datagrid('load', condition);  
        //将查询窗口关闭
        $("#searchWindow").window("close");
    })

    //(自定义的JQuery方法)将表单中所有有name属性的输入项使用serializeArray()方法序列化表单
    //转变为  {"input的name":"input的value"} 的json对象形式,作为datagrid的load方法的查询条件
    $.fn.serializeJson=function(){  
         var serializeObj={};  
         var array=this.serializeArray();  
         var str=this.serialize();  
         $(array).each(function(){  
             if(serializeObj[this.name]){  
                 if($.isArray(serializeObj[this.name])){  
                     serializeObj[this.name].push(this.value);  
                 }else{  
                     serializeObj[this.name]=[serializeObj[this.name],this.value];  
                 }  
             }else{  
                 serializeObj[this.name]=this.value;   
             }  
         });  
         return serializeObj;  
     }; 
</script>
</td>

  T findOne(Specification<T> spec);

JPA中带条件分页查询在下面的接口中

  List<T> findAll(Specification<T> spec);

public interface JpaSpecificationExecutor<T> {  

  Page<T> findAll(Specification<T> spec, Pageable pageable);

Page<T> findAll(Specification<T> spec, Pageable pageable);

  List<T> findAll(Specification<T> spec, Sort sort);

皇牌天下投注网 1

  long count(Specification<T> spec);

所以

  }

public interface CourierDao extends JpaRepository<Courier, Integer>, JpaSpecificationExecutor<Courier> {

皇牌天下投注网,  其中,Page<T> findAll(Specification<T> spec, Pageable pageable)是不是看起来很熟悉,因为在JpaRepository我们用的十分常见,只不过这里的入参不同,Pageable提供了排序分页的功能,Specification允许我们自定义查询条件,继续进入源码:

CourierDao 要继承该接口

public interface Specification<T> {

注意修改泛型T

  Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

Action类中使用Page<Courier> page = courierService.pageQuery(model, pageable);//带两个参的方法

}

model中是提交的查询条件,pageable中是page和rows两个参数

没错,这个接口提供了唯一方法toPredicate,通过该方法构造出一个复杂查询条件。Root代表的是实体,CriteriaBuilder是条件构造器,通过该方法,我们构造出复杂的查询条件并返回,JPA便会自动的处理转换查询。下面以一个小demo描述使用JpaSpecificationExecutor实现复杂查询的步骤:

代码如下:

1、DAO层继承JpaSpecificationExecutor接口(当然,如果需要JpaRepository相关方法,同时继承即可)

@Action("courierAction_pageQuery")
    public String pageQuery() throws Exception {
        Pageable pageable = new PageRequest(page, rows);
        Page<Courier> page = courierService.pageQuery(model, pageable);
        this.java2Json(page, null);
        /*Map<String, Object> map = new HashMap<>();
        map.put("total", page.getTotalElements());
        map.put("rows", page.getContent());

        //将快递员对象中集合属性fixedAreas排除掉(忽略该属性,最终在快递员对象不存在属性)
        JsonConfig jsonConfig = new JsonConfig();
        jsonConfig.setExcludes(new String[]{"fixedAreas", "company"});

        String json = JSONObject.fromObject(map, jsonConfig).toString();
        System.err.println(json);
        ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
        ServletActionContext.getResponse().getWriter().write(json);*/
        return NONE;
    }

@Component
public interface SpeciRepository extends JpaSpecificationExecutor<TestVO>,JpaRepository<TestVO, Long>{
}

但带条件分页查询的方法需要的第一个参数类型为Specification<T> spec 如下

2、Service构造查询条件,并调用DAO层

Page<T> findAll(Specification<T> spec, Pageable pageable);

@Service

所以代码

@Transactional

courierService.pageQuery(model, pageable)

public class MySpeciServiceImpl implements MySpeciService {

在service实现类中要根据model生成Specification的对象才能调用接口中方法

     @Autowired  private SpeciRepository speciRepository;    

return courierDao.findAll(spec , pageable);

  @Override  public Page<TestVO> findByPageAndParams(final TestVO param, int pageNumber,int pageSize) {   

生成对象方法如下:

    Pageable pageable=new PageRequest(pageNumber, pageSize);  //分页信息   

public Page<Courier> pageQuery(final Courier model, Pageable pageable) {
    //封装查询对象Specification
    Specification<Courier> spec = new Specification<Courier>() {

        //封装查询条件: sql: select * from t_courier where 列1 = ? and|or 列2 like ?
        //参数一:根实体,代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似
        //参数二:代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select 、from、where、group by、order by等
        //参数三:用来构建CritiaQuery的构建器对象--产生Predicate(断言)实例工厂
        public Predicate toPredicate(Root<Courier> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

            List<Predicate> list = new ArrayList<>();
            //参数一:从根实体通过导航方式获取属性(表中列)
            //参数二:查询值
            String courierNum = model.getCourierNum();
            String company = model.getCompany();
            String type = model.getType();
            if(StringUtils.isNotBlank(courierNum)){
                //。。。。 where c_courier_num = ?
                Predicate p1 = cb.equal(root.get("courierNum").as(String.class), courierNum);
                list.add(p1);
            }
            if(StringUtils.isNotBlank(company)){
                //  条件 c_company = ?
                Predicate p2 = cb.equal(root.get("company").as(String.class), company);
                list.add(p2);
            }
            if(StringUtils.isNotBlank(type)){
                //  条件 c_type = ?
                Predicate p3 = cb.equal(root.get("type").as(String.class), type);
                list.add(p3);
            }
            //关联查询
            Standard standard = model.getStandard();
            if(standard!=null){
                String standardName = standard.getName();
                if(StringUtils.isNotBlank(standardName)){
                    //创建关联对象 :Standard 默认:JoinType.INNER内连接
                    Join<Object, Object> join = root.join("standard", JoinType.INNER);
                    //查询关联对象中属性
                    Predicate p4 = cb.like(join.get("name").as(String.class), "%" standardName "%");
                    list.add(p4);
                }
            }
            if(list.size()==0){
                return null;    
            }
            Predicate [] predicates = new Predicate[list.size()];
            //将list结合中断言对象存在 数组中predicates
            predicates = list.toArray(predicates);

            // cb.and 相当于查询条件 使用 and 拼接--并且
            // cb.or 相当于查询条件 使用 or 拼接   --或者
            return cb.or(predicates);
        }
    };
    return courierDao.findAll(spec , pageable);
}

    Specification<TestVO> spec = new Specification<TestVO>() {        //查询条件构造       

StringUtils为org.apache.commons.lang3.StringUtils包下工具类

       @Override    public Predicate toPredicate(Root<TestVO> root, CriteriaQuery<?> query,CriteriaBuilder cb) {    

本文由皇牌天下投注网发布于计算机教程,转载请注明出处:序列化表单为json对象,datagrid带额外参提交一次查

关键词:

上一篇:JDK1.8的新特性

下一篇:没有了

最火资讯