1.业务背景
最近负责标签管理业务,因为设计打标签功能就需要用到中间表。在之前的写法,将符合的数据先查询出来在应用层做匹配封装。如果是大表关联性复杂考虑到之后的扩展性,这种写法符合要求的,唯一缺点就是让你代码看的很臃肿,常规做法就是循环匹配,但是代码看起很烦。更好的方法就是将查 出的数据转map,这样时间复杂度会快很多基本上是只需要便利一次。
但是考虑我负责业务背景,他的层级是固定的是两层,虽然我表设计可以无限层,但业务就只需要用到两层。如果是层级不定的还是需要使用上面的方式。
2.代码实现
这是实体类,childs 属性不是数据库字段,用来存放子节点的,
package com.f2bpm.system.models;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.f2bpm.orm.mapper.BaseModel;
import lombok.Data;
import lombok.NonNull;
import lombok.experimental.Accessors;import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;/*** @author 作 者:ljl* @title 标 题: 标签* @date 创建日期:2023-09-06* @copyright 版 权:null* @description 描 述:null*/
@Data
@TableName("tb_tag")
@Accessors(chain = true)
public class Tag /*extends BaseModel */{/*** 标签ID,自增主键*/@NotBlank@TableId(type = IdType.ASSIGN_UUID)private String tagId;/*** 标签名称*/private String tagName;/*** 标签状态,0表示正常,1表示禁用*/@Null(message = "输入类型错误")private Integer tagStatus;/*** 标签类型,0表示标签,1表示分组*/@Null(message = "输入类型错误")private Integer tagType;/*** 创建人*/private String createdBy;/*** 修改人*/private String updatedBy;/*** 备注*/private String remark;/*** 分组*/private String groupId;/*** 是否支持多选 0 支持 1 不支持*/private Integer multiple;/*** 创建时间*/private Date createdTime;/*** 修改时间*/private Date updatedTime;/*** 子节点*/@TableField(exist = false)private List<Tag> childs;}
之前关联的其他表,所有只要将其他类的实体类和字段名对应上即可,但是我是自关联,他有是按照查询列的名字进行关系映射,所以下面采用的是给列起别名的方式。他会将查询的数据映射到我childs 属性里,这样我的sever 层 看起来就简单不少。
<mapper namespace="com.f2bpm.system.mapper.TagMapper"><resultMap id="TagResult" type="com.f2bpm.system.models.Tag"><!--定义表列名和实体属性名之间的映射关系 --><id property="tagId" column="tag_id"/><result property="tagName" column="tag_name"/><result property="tagStatus" column="tag_status"/><result property="tagType" column="tag_type"/><result property="createdBy" column="created_by"/><result property="updatedBy" column="updated_by"/><result property="remark" column="remark"/><result property="createdTime" column="created_time"/><result property="updatedTime" column="updated_time"/><result property="groupId" column="group_id"/><result property="multiple" column="multiple"/><collection property="childs" ofType="com.f2bpm.system.models.Tag"><!-- 定义子标签的映射关系 --><id property="tagId" column="childTagId"/><result property="tagName" column="childTagName"/><result property="tagStatus" column="childTagStatus"/><result property="tagType" column="childTagType"/><result property="createdBy" column="childCreatedBy"/><result property="createdTime" column="childCreatedTime"/></collection></resultMap><sql id="selectTagVo">SELECT t1.tag_id as tag_id,t1.tag_name as tag_name,t1.tag_status as tag_status,t1.tag_type as tag_type,t1.created_by as created_by,t1.created_time as created_time,t1.multiple as multiple,t1.group_id as group_id,t2.tag_id AS childTagId,t2.tag_name AS childTagName,t2.tag_status AS childTagStatus,t2.tag_type AS childTagType,t2.created_by AS childCreatedBy,t2.created_time AS childCreatedTime,t2.multiple AS childIsMultipleFROM tb_tag t1LEFT JOIN tb_tag t2 ON t1.tag_id = t2.group_id</sql><select id="getList" resultMap="TagResult" parameterType="com.f2bpm.system.models.dto.TagDto"><include refid="selectTagVo"/><where>t1.group_id IS NULL<if test="groupName != null and groupName != ''">AND t1.tag_name LIKE CONCAT('%', #{groupName}, '%')</if><if test="multiple != null">AND t1.multiple = #{multiple}</if><if test="state != null">AND t1.tag_status = #{state}AND t2.tag_status = #{state}</if><if test="tagNames != null and tagNames.size() != 0 ">AND t2.tag_name = #{tagNames.get(0)}</if></where>ORDER BY t1.created_time, t1.updated_time DESC</select>
总结
数据库 关联还是需要确定表的量级, 不然结果集过大必然导致查询数据变慢