ibatis分组查询结果的返回参数绑定问题解决方案

  • 这次需求是从两个表里取出数据。最开始是在dao层中直接取出一张表中的所有记录,因为一张表对应一个实体类,这样取出所有记录,一些逻辑上的业务可以在程序中去处理,这样虽然导致代码量比较大,但是是比较容易理解的方法。
  • 首先我们来看两张表的结构。
    这里写图片描述

    这里写图片描述

  • 这里的规范是不设置外键,关系尽量用单独的表去保存,这应该接近第三范式。这样不用去考虑复杂的父表子表参照完整性,的确方便了很多,因此这里使用ibatis可以更好的从sql语句去查询优化吧。

  • 最开始我新建了一个对应BirthPlace的实体类,属性对应字段,这个表的id_card对应第二章表里的id,也就是也要通过第一张表里id_card查到到对应的province和city两个粒度下去求同省份或则同城市的人口总和。先把明确的部分先解决吧,实体类搞好了,确定需要查询的记录,这里我首先在console里去构建sql语句。
    我的sql语句是:
select city as origin_name, population as origin_population from t_mon_base_id_card,t_mon_data_birth_place WHERE area_id = 1000 and date_time >= '2015-07-20' and date_time <= '2015-10-10' and t_mon_data_birth_place.id_card = t_mon_base_id_card.id group by city
;

查询粒度为城市,分组查询一般跟聚合函数一起使用,这条sql语句就是通过两张表查到同一个城市的人数和并按照城市将其列出。
结果为:
这里写图片描述
如果将粒度改为省份:
这里写图片描述
核对了记录确认无误,因此sql语句是没问题的。

  • 到这里,我们可以明确queryMap需要传入的参数了,startTime与endTime与area_id和操作粒度,操作粒度可以在程序里去判断,分解成两个方法分别查询出城市和省份的sql语句。
  • 但是在写mapper的时候遇到了一个问题,需要返回的参数,只需要显示来源地(无论是城市还是省份)和对应来源地的人数。返回参数我该怎么写呢,最开始考虑用util.Map去返回参数,key为origin_name,value为origin_population。但是如果让结果一个字段去匹配key,另一个字段去匹配value,这个问题我去查找相关解决方案,大都是搞得十分复杂,看来ibatis并没有给予原生的支持这种匹配方式,因此我又考虑回了List。
  • 后来我在实体类里添加了两个属性:
private String originName;//查询结果保留属性
private Integer originPopulation;//查询结果保留属性

这样我可以在查询结果映射这个实体类,然后将两个参数绑定到这两个属性上,其他属性为null值,没有什么影响。我感觉是非常好的思路。我在SQL语句里无论是城市还是省份,都将查询结果用as origin_name的方式统一命名,这样在resultMap中可以用一个map去绑定属性,十分巧妙。

  • sqlmapper:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cmcc.monitor.dao.data.BirthPlaceDao">

    <resultMap type="com.cmcc.monitor.entity.data.BirthPlace" id="BirthPlaceList">
        <result column="origin_name" property="originName" />
        <result column="origin_population" property="originPopulation" />
    </resultMap>

    <select id="getBirthPlacePopulationByCity" parameterType="java.util.Map"
        resultMap="BirthPlaceList">
        select
        city as origin_name,
        sum(population) as origin_population
        from
        t_mon_base_id_card,t_mon_data_birth_place
        <where>
            <if test="areaId != null">
                area_id = #{areaId}
            </if>
            <if test="startTime != null">
        <![CDATA[and date_time >= #{startTime}]]>
            </if>
            <if test="endTime != null">
        <![CDATA[and date_time <= #{endTime}]]>
            </if>
            and t_mon_data_birth_place.id_card = t_mon_base_id_card.id
        </where>
        group by city;
        </select>

    <select id="getBirthPlacePopulationByProvince" parameterType="java.util.Map"
        resultMap="BirthPlaceList">
        select
        province as origin_name,
        sum(population) as origin_population
        from
        t_mon_base_id_card,t_mon_data_birth_place
        <where>
            <if test="areaId != null">
                area_id = #{areaId}
            </if>
            <if test="startTime != null">
        <![CDATA[and date_time >= #{startTime}]]>
            </if>
            <if test="endTime != null">
        <![CDATA[and date_time <= #{endTime}]]>
            </if>
                and t_mon_data_birth_place.id_card = t_mon_base_id_card.id
        </where>
        group by province;
    </select>
</mapper>
  • 由于一些原因,在action里的业务逻辑就不展示了,主要是获取url提交的areaId与startDate与endDate参数还有操作粒度,最后通过不同的粒度去查询出城市或则省份的列表,最后通过JSON返回给前端。
  • 将dao与manager的定义和注入补齐。
  • 测试(按省粒度):
路径名/birth-place!display.action?areaId=1000&startDate=2015-07-01&endDate=2015-10-10&kpiCycle=province

这里写图片描述

  • 成功实现需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值