mybatis使用的奇技淫巧

合并多行查询的结果

业务需求

商家可以根据商品类目分类,每位商家可以有多个商品类目,商品类目又跟运营类目有一种关联规则。此处暂且不说运营类目。根据业务,商家信息是一张表,商家与商品类目有一张关联表,商品类目有一张表,权且使用三张表。

其他不相干字段不展示

  • 商家表(user)

uidusernamemobile
1张三12345678901
2李四12345600002
  • 商品类目表(item_category)

icidnamestatusparentid
1服装00
2茶具00
3食品00
  • 商家与商品类目(user_item_cate_rel)

uidicid
11
12
21
23

如果我们需要在前端页面展示每个商家的商品类目,那么我们返回的结果中就需要每条商家数据中包含所属商品的类目。实现方式有很多种:1.一条sql语句可以实现,使用group_concat函数并根据uid分组2.先查询商家信息,再根据商家uid查询user_item_cate_rel和item_category表,再将结果在model中组合3.用mybatis的resultMap。此处只看1和3的实现方式。

  • 展示需求:

#商家ID商家名手机号码商品类目操作
11张三12345678901服装,茶具 删除 修改
22李四12345600002服装,食品 删除 修改

group_caoncat实现

SELECT u.*,group_concat(ic.name) categories FROM user 
LEFT JOIN user_item_cate_rel uicr
ON u.uid = uicr.uid
LEFT JOIN item_category ic
ON uicr.icid = ic.icid
WHERE ... # 查询条件
GROUP BY u.uid

大概就这样,可以把类目直接返回给前端,毫无疑问,这个实现是最快的。但是,当数据量大的时候,并且是查询列表的时候,全表扫描,就会出现慢查询。

巧妙使用Mybatis resultMap

创建User和Category POJO。User除了user表的字段作为属性外,外加一个private List<Category> categories属性。Category的字段分别为:icidname

mapper的xml中:

  • 先定义一个id为user的resultMap:

<resultMap id="user" type="User" autoMapping="true">
    <collection property="categories" ofType="Category" select="getCategory" column="uid" javaType="ArrayList">
        <id property="icid" column="icid"/>
        <result property="name" column="name"/>
    </collection>
</resultMap>
  • 实现select属性对应方法:此处select的id为上面id为user的resultMap中collection的select元素,参数#{uid}为column元素指定的字段。

<select id="getCategory" resultType="Category">
    SELECT uicr.icid,ic.name FROM user_item_cate_rel uicr
    LEFT JOIN item_category ic
    ON uicr.icid = ic.icid
    WHERE uicr.uid = #{uid}
</select>
  • 获取指定条数的数据:mybatis可以根据传入的参数组装sql语句。

<select id="getUsers" parameterType="UserSearch" resultMap="user">
    SELECT u.* FROM user u LEFT JOIN user_item_cate_rel uicr 
    ON u.uid = uicr.uid
    WHERE 1=1
    <if test="uid != null"> AND u.uid = #{uid} </if>
    <if test="username != null"> AND u.username LIKE concat('%',#{username}, '%')</if>
    <if test="mobile != null"> AND u.mobile = #{mobile}</if>
    <if test="icid != null"> AND uicr.icid = #{icid}</if>
    ..... // 各种查询条件
    LIMIT #{page},#{offset}
</select>

上面查询中,UserSearch是查询条件POJO,可以根据需要自定义过滤那些字段。其中有一个属性是icid,就是根据传入的一个商品类目查询商家信息。比如,要查询icid=1的商家,那么我们返回的数据不仅仅是icid=1的,还应该是icid=1商家的其他icid信息。

那么查询结果应该为:

[
    {
        "uid": 1,
        "username": "张三",
        "mobile": "12345678901",
        "categories": [
            {
                "icid": 1,
                "name": "服装"
            },
            {
                "icid": 2,
                "name": "茶具"
            }
        ]
    },
    {
        "uid": 2,
        "username": "李四",
        "mobile": "12345600002",
        "categories": [
            {
                "icid": 1,
                "name": "服装"
            },
            {
                "icid": 3,
                "name": "服装"
            }
        ]
    }
]

此处需要注意一点,resultMap的select元素调用getCategory方法时,自动映射的属性名和列名应该保持一致,或者列表必须是数据库表中的字段名,而不是别名。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值