业务场景
一条数据需要针对某个字段做特殊的扩展处理,比如:为用户设置某些特定的标签(标签包含排序、代码、名字)
方案对比
多字段存储(不推荐)
在主表中新增tag_sort、tage_code、tag_name,多个标签使用特殊字符分割且存储顺序需要一一对应,示例:
tag_sort=1,2,3
tage_code=tall,rich,cool
tag_name=高,富,帅
子表(推荐)
新建tag表,存储关联用户的id、排序、代码、名字。
扩展字段使用json类型存储(推荐)
直接使用tag字段存储json数据,示例:
tag=[
{"tag_sort":1,"tage_code":"tall","tag_name":"高"},
{"tag_sort":2,"tage_code":"rich","tag_name":"富"},
{"tag_sort":3,"tage_code":"cool","tag_name":"帅"}
]
准备工作
MySQL 版本 >= 8.0
-- 新建测试表
CREATE TABLE `demo`.`user` (
`id` bigint(32) NOT NULL COMMENT '主键id',
`name` varchar(50) NULL COMMENT '名称',
`tag` json NULL COMMENT '标签',
PRIMARY KEY (`id`)
);
案例
使用扩展字段方式
版本
mybatis 3.5.1
mybatis-plus 3.5.2
示例代码
查询所有包含高、富、帅三个标签的用户
SQL实现
SELECT u.*
FROM user u,
JSON_TABLE(
u.tag,
'$[*]'
COLUMNS(
tag_code VARCHAR(255) PATH '$.tag_code',
tag_sort_no INT PATH '$.tag_sort_no'
)
) AS u
WHERE u.tag_code IN (1, 2, 3)
order by id
mybatis-plus实现
// 代码示例
List<String> tagCodes = dto.getTagCodes();
List<UserEntity> existConfigs = new LambdaQueryChainWrapper<>(this.userMapper)
.and(wrapper -> {
Iterator<String> it = tagCodes.iterator();
while (it.hasNext()) {
wrapper.apply("JSON_CONTAINS(tag, JSON_OBJECT('tag_code',{0}))", it.next());
wrapper.or();
}
})
.orderByAsc(UserEntity::getId)
.list();
更多使用语法参考:MySQL-JSON函数手册