【MyBatis】foreach实现postgresql的json类型数据的集合包含遍历查询

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Mr_EvanChen/article/details/82021995

目录

需求描述

解决思路

运行结果


需求描述

       如下图所示,sub_rule表的detail字段是json类型的(数据库采用的是postgresql),里面存的是预先定义好的规则,例如某规则是{"开发类型":["新功能","优化细节交互"], "代码规模":["100-500行","500-100行"], "开发能力":["1A","1B","2A"]},则通过这条规则的任务就是需求分析1。

       其中开发类型、代码规模、开发能力表示3个大维度,是与的关系,需要同时满足;各自下面又有子维度,是或的关系,通过一个即可。

      假设这时候有某个任务,它的评估规则是{"开发类型":["新功能"], "代码规模":["0-100行"], "开发能力":["1A","1B"]},那么它匹配数据库中所有规则的结果应该是需求分析2。再举个栗子,假设有个任务的评估规则是{"开发类型":["新功能"], "开发能力":["1B","2A"]},那么它匹配数据库中所有规则的结果应该是设计1,它缺少代码规模维度,因此不应该通过需求分析1。

解决思路

       传进来的数据data应该是要类似json的格式,这里采用map。那么首先,应该能够遍历map的key,拿到对应的value1;其次,拿到json数据中key对应的value2;比较两个value,满足value1包含于value2。但这里还会有一个问题,就是上述的第二个例子,若任务的评估规则是{"开发类型":["新功能"], "开发能力":["1B","2A"]},那么以map来进行循环,这样仅会循环两个大维度,且相应的子维度有满足条件了,不会再判断其他维度,因此得到了设计1和需求分析1。针对这种情况,可以加上一个维度大小的判断,即表中的dimension_size字段,先过滤到大维度不一样的规则,再循环判断。

运行结果

       服务方法,构造map,模拟规则{"开发类型":["新功能"], "开发能力":["1B","2A"]}

    public List<SubRule> findRuleByDimensionId() {

        Map<String, List<String>> con = new HashMap<>();

        List<String> list = new ArrayList<>();
        list.add("\"新功能\"");
//       list.add("\"优化细节交互\"");

//       List<String> list2 = new ArrayList<>();
//       list2.add("\"100-500行\"");

        List<String> list3 = new ArrayList<>();
        list3.add("\"2A\"");
        list3.add("\"1B\"");

        con.put("开发类型", list);
//        con.put("代码规模", list2);
        con.put("开发能力", list3);

        List<SubRule> subRules = indexMapper.findRuleByDimensionId(con, 2);

        for (SubRule subRule : subRules) {
            System.out.println(subRule);
        }
        return subRules;
    }

       mapper中的查询语句,这里用到postgresql的知识,中文文档链接:http://www.postgres.cn/docs/9.5/datatype-json.html

扫描二维码关注公众号,回复: 3815991 查看本文章
    <select id="findRuleByDimensionId" resultMap="subRuleVO" parameterType="java.util.Map">
        SELECT * FROM sub_rule WHERE sub_rule.dimension_size = #{dimensionSize} AND
        <foreach collection="con" index="key" item="values" separator="and" >
            (sub_rule.detail::json#>>'{${key}}')::jsonb @> '${values}'
        </foreach>
    </select>

      关于foreach的知识

item 循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。
具体说明:若collection属性为list或array,则item代表list或array里面的一个元素。若collection属性对应一个map,则item代表的是map中的value集合中的单个value
该参数为必选。
collection

foreach遍历的对象,作为入参时,List对象默认用list代替作为键,数组对象有array代替作为键,Map对象没有默认的键。也就是传入的集合(list,array,map)的名字,这个名字可以在foreach里面随便引用)
当然在作为入参时可以使用@Param("params")来设置键,设置keyName后,list,array将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:
如果User有属性List ids。入参是User对象,那么这个collection = "ids"
如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id"

如果传入参数类型为map,这个入参有注解@Param("params"),则map的所有的key集合可以写成params.keys,所有值集合可以写成params.values。这样foreach就可以对key集合或值集合进行迭代了。

上面只是举例,具体collection等于什么,就看你想对那个元素做循环。
该参数为必选。

separator 元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
open foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。
close foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
index 在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。

        从结果可以看出来,确实只得到了设计1,而没有需求分析1。

猜你喜欢

转载自blog.csdn.net/Mr_EvanChen/article/details/82021995
今日推荐