【Mybatis整合mysql之Json类型属性适配&&手把手】
场景
JSON 数据类型是 MySQL 5.7.8 开始支持的。在此之前,只能通过字符类型(CHAR,VARCHAR 、TEXT或LONGTEXT )来保存 JSON 文档。在开发中发现,Mybatis查询Json字段时,发现不能映射,如下:
java实体:
@Data public class ApiGatherProject extends Base { /** * id */ private Long id; /** * 项目id */ private Long projectId; /** * sap接口url */ private String url; /** * 请求类型 0:GET 1:POST 2:PUT 3:DELETE */ private Integer httpType; /** * 请求参数列表 */ private JSONArray requestParamList; /** * 检验条件 0:默认响应码200 1:自定义响应码 2:内容包含 3:内容不包含 */ private Integer checkCondition; /** * 检验内容 */ private String checkContent; /** * 路由 */ private String route; /** * api类型:0 自定义 */ private Integer apiType; /** * json类型:0 application/json */ private Integer jsonType; }
复制
mybatis config.xml
如下:
<mapper namespace="com.mapper.ApiGatherProjectMapper"> <resultMap id="resultList" type="com.test.entity.ApiGatherProject"> <id column="id" property="id"></id> <result column="project_id" property="projectId"></result> <result column="url" property="url"></result> <result column="http_type" property="httpType"></result> <result column="request_param_list" property="requestParamList"></result> <result column="check_condition" property="checkCondition"></result> <result column="check_content" property="checkContent"></result> <result column="api_type" property="apiType"></result> <result column="json_type" property="jsonType"></result> <result column="route" property="route"></result> <result column="creator_id" property="creatorId"></result> <result column="create_time" property="createTime"></result> <result column="modify_time" property="modifyTime"></result> </resultMap> <insert id="add" useGeneratedKeys="true" keyProperty="id"> INSERT INTO t_gather_api (project_id, url, http_type, request_param_list, check_condition, check_content, api_type, json_type, route) VALUES (#{projectId}, #{url}, #{httpType}, #{requestParamList}, #{checkCondition}, #{checkContent}, #{apiType}, #{jsonType}, #{route}) </insert> <delete id="batchDeleteByProjectIds"> DELETE FROM t_gather_api WHERE project_id IN <foreach collection="projectIds" item="projectId" open="(" separator="," close=")"> #{projectId} </foreach> </delete> <delete id="batchDelete"> DELETE FROM t_gather_api WHERE id IN <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete> <select id="getById" resultMap="resultList"> SELECT * FROM t_gather_api WHERE id = #{id} </select> <select id="getByProjectId" resultMap="resultList"> SELECT * FROM t_gather_api WHERE project_id = #{id} </select> </mapper>
复制
mysql数据库中,requestParamList
字段有数据,如下:
对于JSONArray
类型 requestParamList
字段,服务启动不了,报如下错误:
Caused by: java.lang.IllegalStateException: No typehandler found for property requestParamList at org.apache.ibatis.mapping.ResultMapping$Builder.validate(ResultMapping.java:151) at org.apache.ibatis.mapping.ResultMapping$Builder.build(ResultMapping.java:140) at org.apache.ibatis.builder.MapperBuilderAssistant.buildResultMapping(MapperBuilderAssistant.java:446) at org.apache.ibatis.builder.xml.XMLMapperBuilder.buildResultMappingFromContext(XMLMapperBuilder.java:393) at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:280) at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:254) at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElements(XMLMapperBuilder.java:246) at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:119)
复制
原因分析
Caused by: java.lang.IllegalStateException: No typehandler found for property requestParamList`
复制
出现该异常,大致原因是是因为requestParamList属性的类型无法和mysql映射!
从该问题入手后,发现mybatis目前不支持Json字段的的处理,如下包:
org.apache.ibatis.type.*;
复制
找不到Json的Handler,哦 my gay,好像找到问题了,我决定仿照org.apache.ibatis.type.ArrayTypeHandler
自定义一个JsonTypeHandler
,看到这里,是不是觉得我很牛逼,no no no,去掉牛!!!!
解决方案
自定义JsonTypeHandler
:
package com.test.handler; import org.apache.ibatis.type.*; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import org.springframework.context.annotation.Configuration; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @MappedTypes(JSONArray.class) // 指定映射的目标类型为 JSONArray @Configuration public class JsonTypeHandler extends BaseTypeHandler<JSONArray> { @Override public void setNonNullParameter(PreparedStatement ps, int i, JSONArray parameter, JdbcType jdbcType) throws SQLException { String jsonString = JSON.toJSONString(parameter); ps.setString(i, jsonString); } @Override public JSONArray getNullableResult(ResultSet rs, String columnName) throws SQLException { return parseJson(rs.getString(columnName)); } @Override public JSONArray getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return parseJson(rs.getString(columnIndex)); } @Override public JSONArray getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return parseJson(cs.getString(columnIndex)); } private JSONArray parseJson(String jsonString) { if (jsonString == null || "".equals(jsonString)) { return new JSONArray(); } else { return JSON.parseArray(jsonString); } } }
复制
适配mbatis 的Xml文件中的,如下,主要关注request_param_list
<resultMap id="resultList" type="com.entity.ApiGatherProject"> <id column="id" property="id"></id> <result column="project_id" property="projectId"></result> <result column="url" property="url"></result> <result column="http_type" property="httpType"></result> <result column="request_param_list" property="requestParamList" javaType="com.alibaba.fastjson.JSONArray" jdbcType="OTHER" typeHandler="com.cctegitc.warehouse.handler.JsonTypeHandler"></result> <result column="check_condition" property="checkCondition"></result> <result column="check_content" property="checkContent"></result> <result column="api_type" property="apiType"></result> <result column="json_type" property="jsonType"></result> <result column="route" property="route"></result> <result column="creator_id" property="creatorId"></result> <result column="create_time" property="createTime"></result> <result column="modify_time" property="modifyTime"></result> </resultMap>
复制
重启服务,测试:
成功了!!!!!看着很简单吧,看到这里了,求个小关小赞吧,家人们 /笑。
写到最后
作为一个程序员,公认的都是很忙的,但是,我就很“闲”了,开发工作游刃有余,但就是太闲了,哈哈哈,因为我的领导也很闲呀,上班8小时,谝传4小时,上厕所2小时,接水1小时,剩余1小时给我安排任务,阿达。。。
作为小小程序员,最近也开始研究“伏羲一画开天下”,八卦图,哈哈【乾三连,坤六断,震仰盂,艮覆碗,离中空,坎中满,兑上缺,巽下断】,当我慢慢深入发现,没有比程序员更适合学习《易经》的人了,因为我们的逻辑思维很强呀,,哈哈,我去上个厕所,下期见