• 序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询 多表关联查询


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

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

    转换方法看代码注释

    <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>

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

    public interface JpaSpecificationExecutor<T> {  

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

    所以

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

    CourierDao 要继承该接口

    注意修改泛型T

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

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

    代码如下:

    @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;
        }

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

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

    所以代码

    courierService.pageQuery(model, pageable)

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

    return courierDao.findAll(spec , pageable);

    生成对象方法如下:

    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);
    }

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

    其中断言的值有好几个

    拼接的时候需要提供一个断言的数组

    return cb.or(predicates );

    而数组是定长的,我们又不确定有几个断言

    所以只能创建一个可变长度的数组,那么就需要设置数组长度使用一个变量,使用list.size()

    Predicate [] predicates = new Predicate[list.size()];

    将集合变为指定类型的数组使用其toArray()方法,无惨转为Object[],有参转为指定类型的数组

    predicates = list.toArray(predicates);

    如果没有额外条件,就是一个正常的分页查询

                if(list.size()==0){
                    return null;    
                }

    这时

    return courierDao.findAll(spec , pageable);

    spec为空


    如果查询条件在实体的关联对象中,则需要多表关联查询

    不能直接使用root,直接使用root.get("name")得到的是当前实体(courier)中的name,我们要的是关联实体(standard)的name属性

    所以要得到关联对象join,通过standard对象(属于Courier实体的属性即可)关联,默认是内连接,也可以左外右外连接

    Join<Object, Object> join = root.join("standard", JoinType.INNER);

    通过关联对象进行查询即可

    Predicate p4 = cb.like(join.get("name").as(String.class), "%"+standardName+"%");


    datagrid这个ajax请求的好处就在于发送的请求不会刷新浏览器,所以查询的条件会一直在,不会影响到分页

  • 相关阅读:
    MySQL中interactive_timeout和wait_timeout的区别
    MySQL主从环境下存储过程,函数,触发器,事件的复制情况
    Hbase的伪分布式安装
    当master down掉后,pt-heartbeat不断重试会导致内存缓慢增长
    ERROR 1010 (HY000): Error dropping database (can't rmdir './test/', errno: 17)
    基于MySQL MEB的备份恢复
    pt-heartbeat
    B树和B+树的区别
    如何在Zabbix上安装MySQL监控插件PMP
    如何部署Zabbix服务端
  • 原文地址:https://www.cnblogs.com/qingyundian/p/9234556.html
Copyright © 2020-2023  润新知