JSON类型是MySQL5.7.8中新加入的一种数据类型,并在后续版本尤其是MySQL8.0中得到了大幅增强,现在的JSON类型的功能十分强大,合理使用能让我们的开发更加有效!
但本文不准备花篇幅来介绍MySQL的JSON类型字段的相关API,因为官方文档里面写得已经十分详细了,大家如果对MySQL的JSON类型还不怎么了解的话可以看看官方文档:
(ps:英语相对较差的小伙伴可以用chrome浏览器打开,然后用自带的翻译工具翻译后看哦~)
JSON的应用场景还是挺多的,我能想到的两个是:
数据字典
动态表单
功能方面需要明确的是:
枚举选项是严禁直接删除的。
枚举选项的键是严禁修改的。
可以增加一些辅助功能。
CREATE TABLE `sys_dict` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` varchar(30) NOT NULL COMMENT '编码', `name` varchar(40) NOT NULL COMMENT '展示名称', `content` json NOT NULL COMMENT '内容', /* 下面六个字段根据需要增加 */ `description` varchar(200) DEFAULT NULL COMMENT '描述', `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 [0未删除 1已删除]', `create_by` int(11) DEFAULT NULL COMMENT '创建人', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_by` int(11) DEFAULT NULL COMMENT '修改人', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统字典表';
@Getter @Setter @TableName(value = "sys_dict", autoResultMap = true) @ApiModel("系统字典实体类") public class SysDict extends BaseDO { @TableId(type = IdType.AUTO) //id自增 private Integer id; @ApiModelProperty("编码") private String code; @ApiModelProperty("名称") private String name; @TableField(typeHandler = JacksonTypeHandler.class) @ApiModelProperty("内容列表") private List<DictContent> content; @Getter @Setter @NoArgsConstructor @ApiModel("系统字典内容实体类") public static class DictContent { @ApiModelProperty("键") private Integer key; @ApiModelProperty("值") private String value; @ApiModelProperty("排序,数字越小越前面") private Integer order; @ApiModelProperty("是否删除 [0:未删除 1:已删除]") private Integer deleted; //辅助字段根据需求来定,有必要的情况下可以继承BaseDO,增加那6个字段! } } @Getter @Setter public abstract class BaseDO implements Serializable { @ApiModelProperty("备注") private String description; @ApiModelProperty("是否删除 [0:未删除 1:已删除]") private Integer deleted; @ApiModelProperty("创建人") private Integer createBy; //JSONFormat是格式化时间的输入输出格式 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") @ApiModelProperty("创建时间") private LocalDateTime createTime; @ApiModelProperty("修改人") private Integer updateBy; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8") @ApiModelProperty("修改时间") private LocalDateTime updateTime; }
这里为了方便,将创建修改信息等6个字段抽象出来了,以后创建实体类就直接继承该类就行,同时该类声明了序列化,所以其子类也不需要再单独实现Serializable接口,一举多得~
这里有两个个细节:
通过Mybatis Plus注解实现
上文中的@TableName和@TableField是Mybatis Plus提供的注解,@TableName的autoResultMap属性一般与content字段的@TableField的typeHandler属性一起使用,表示会自动创建resultMap处理查询返回值,但这个操作仅限于Mybatis Plus提供的查询方法,自定义方法不会自动创建。
通过ResultMap实现
需要注意的是:如果你在对应的Mapper文件中自定义了类型为这个实体类的ResultMap的话,上述操作也不会执行。也就是说如果需要自定义ResultMap,则需要手动增加typeHandler属性:
没有使用Mybatis Plus的小伙伴也是通过下述这种方式进行类型转换~~
<!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.copm.ifm.servers.insp.entity.SysDict"> <id column="id" property="id" /> <result column="code" property="code" /> <result column="name" property="name" /> <!-- 这里显示指定typeHandler属性值 --> <result column="content" property="content" jdbcType="JAVA_OBJECT" javaType="java.util.List" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> <result column="description" property="description" /> <result column="deleted" property="deleted" /> <result column="create_by" property="createBy" /> <result column="create_time" property="createTime" /> <result column="update_by" property="updateBy" /> <result column="update_time" property="updateTime" /> </resultMap>
上述代码中使用的jdbcType="JAVA_OBJECT"中,jdbcType的取值范围来源于org.apache.ibatis.type.JdbcType枚举。
content的javaType不要写成了SysDict#DictContent 哦!他的java类型是List,DictContent是List的泛型。
只要存在type=“com.copm.ifm.servers.insp.entity.SysDict” 的resultMap,就会使Mybatis Plus的 @TableName(autoResultMap = true) 失效。
昨天在实际应用过程中遇到了泛型擦除问题,如下图,content字段List的泛型明明是DictContent,但是其实际泛型却是LinkedHashMap!所以在后面的遍历时报类型转换失败的错,这就是典型的泛型擦除问题!
详细解决方案请看:>>泛型擦除问题解决传送门<<
解决方案1:
自定义一个指定泛型的集合类替代List<T>即可。
8.11新增:解决方案2:
本文通过swagger文档添加操作进行效果展示
JSON类型的功能十分强大,可以通过MySQL提供的JSON相关的方法直接操作JSON字段中的某个属性值,也可以针对JSON类型字段的数据进行各种操作。
相对于使用字符串类型保存JSON字符串的方式而言,使用JSON类型的另外一个好处是可以在程序上定义JSON格式,提供更友好而规范的API文档。
另外如果不想使用JSON类型,直接用Varchar类型也是可以的哦!如果用JSON类型可以根据JSON对象的字段进行条件查询!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。