专栏首页工作笔记精华Springboot+Mybatis+MySql下,mysql使用json类型字段存取的处理

Springboot+Mybatis+MySql下,mysql使用json类型字段存取的处理

1、mysql5.7开始支持json类型字段; 2、mybatis暂不支持json类型字段的处理,需要自己做处理

项目使用到了这个,网上查了一些资料,实践成功,做记录。 第一步:建表

CREATE TABLE rules_test(
id INT PRIMARY KEY AUTO_INCREMENT,
sys_name VARCHAR(16) NOT NULL unique,
rules JSON,
date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

第二步:使用generator自动生成xml文件,entity(实体)文件,mapper文件

RulesTestMapper.xml
RulesTest.java
RulesTestMapper.java

第三步:建包com.xxx.xxx.handler,新建MySqlJsonHandler.java,内容如下:

package com.xxx.xxx.handler;

import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * @Project 
 * @Autor 
 * @Create 2019/7/16 1:32 PM
 * @Description
 */
@MappedTypes(JSONObject.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class MySqlJsonHandler extends BaseTypeHandler<JSONObject>{
    /**
     * 设置非空参数
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i,String.valueOf(parameter.toJSONString()));
    }
    /**
     * 根据列名,获取可以为空的结果
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }
    /**
     * 根据列索引,获取可以为内控的接口
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String sqlJson = rs.getString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }
    /**
     *
     * @param cs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String sqlJson = cs.getNString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson);
        }
        return null;
    }
}

第四步:在application.yml中增加对应配置

mybatis:
  mapper-locations: classpath:mapper/*.xml   
  type-aliases-package: com.xxx.xxx.entity   
  type-handlers-package: com.xxx.xxx.handler  #增加此项配置

第五步:修改RulesTestMappler.xml中对应部分 第一个地方---->

<resultMap id="BaseResultMap" type="com.xxx.xxxx.entity.RulesTest" >
    <!--
      WARNING - @mbggenerated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="sys_name" property="sysName" jdbcType="VARCHAR" />
    <!--将json类型的rules字段修改为如下形式-->
    <result column="rules" property="rules" typeHandler="com.xxx.xxx.handler.MySqlJsonHandler" />
    <result column="date" property="date" jdbcType="TIMESTAMP" />
  </resultMap>

其他地方----> PS:在xml中写sql语句时,需要将使用到rules的地方配置,以下以插入为例

<insert id="insertTest" parameterType="com.xxx.xxx.entity.RulesTest" >
    <!--
      WARNING - @mbggenerated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    insert into rules_test (id, sys_name, rules,
    date)
    values (#{id,jdbcType=INTEGER}, #{sysName,jdbcType=VARCHAR}, #{rules,jdbcType=OTHER,typeHandler=com.xxx.xxx.handler.MySqlJsonHandler},
    #{date,jdbcType=TIMESTAMP})
  </insert>

第六步:修改RulesTest.java实体文件中,rules对应的属性修改为JSONObejct,以下仅摘取修改相关代码

import com.alibaba.fastjson.JSONObject;
//属性
private JSONObject rules;
//get方法
public JSONObject getRules() {
        return rules;
    }
//set方法
public void setRules(JSONObject rules) {
        this.rules = rules == null ? null : rules;
    }

至此,所有相关修改都已经修改完了,按照正常的步骤进行开发即可~

参考链接: 1、SpringBoot中MyBatis 处理 MySQL5.7 的json字段数据 2、MyBatis针对Mysql中json字段的类型处理

SpringBoot中MyBatis 处理 MySQL5.7 的json字段数据

最近学习过程中遇到一个需要将订单数据存入数据库需求,项目是使用 SpringBoot+MyBatis 框架,数据库是 MySQL,订单数据格式如下:

   { 
 
 
   
 
   all_price: 32 
 
 
   
 
   beizhu: "暂无" 
 
 
   
 
   store_id: "1" 
 
 
   
 
   goods: [ 
 
 
   
 
   {goods_id: 2,goods_name: "辣椒炒肉",goods_num: 2}, 
 
 
   
 
   {goods_id: 5,goods_name: "扬州炒饭",goods_num: 1}, 
 
 
   
 
   {goods_id: 6,goods_name: "蛋炒饭",goods_num: 1}] 
 
 
   
 
   usemessage: { 
 
 
   
 
   cityName: "广州市" 
 
 
   
 
   countyName: "海珠区" 
 
 
   
 
   detailInfo: "新港中路397号" 
 
 
   
 
   postalCode: "510000" 
 
 
   
 
   provinceName: "广东省" 
 
 
   
 
   telNumber: "020-81167888" 
 
 
   
 
   userName: "张三" 
 
 
   
 
   } 
 
 
   
 
   } 
 
 

而我想把 goodsusemessage 这两个比较复杂的数据当成分别一个字段去处理,不想拆分里面的字段,之前没有将 json 格式数据插入 MySQL 数据库的经验,插入的都是拆分后的一个一个字段,如果我想保留数据格式存入数据库又如何处理呢??脑壳疼!!

网上查询后,了解到 MySQL 5.7.8 以后版本居然加入了 json 字段,沃德天,好惊喜啊哈哈哈!!!这下有搞头了!

赶紧查了一下我的 MySQL 版本:是大于 V5.7.8 的,在支持范围内

 等等,我怎么在Navicat 上怎么找不到 json 字段类型   

,又是一番查找,原来 Navicat 版本太低不支持。。。所以我又升级到 Navicat Premium 12 版本了,这下 json 字段出来了,那这个 json 字段类型对应的 Java bean 属性又是什么呢?MyBatis 怎么写 sql 呢?

又是一番查找。。。

额,MyBatis 还不支持直接处理MySQL json字段。。。只能通过自定义 TypeHandler 来转化,行吧,那就写呗。不过之前要看看 goodsusemessage 这两个是有区别的,所以我分别转成了 JSONArray、JSONObject ( 选择 com.alibaba.fastjson 工具类下的)

   
 
   JSONArray goodslist=data.getJSONArray("goods"); 
 
 
   
 
   JSONObject usemessage= data.getJSONObject("usemessage"); 

 

所以对应的也要自定义两种不同 TypeHandler 来分别适配 ,在此之前,由于我使用的是  fastjson 这个工具类包,所以要在 pom.xml 中先引入:

 <!--添加fastjson依赖--> 
 
 
   
 
   <dependency> 
 
 
   
 
   <groupId>com.alibaba</groupId> 
 
 
   
 
   <artifactId>fastjson</artifactId> 
 
 
   
 
   <version>1.2.7</version> 
 
 
   
 
   </dependency> 
 

然后就是两个自定义 TypeHandler 了:首先是ArrayJsonHandler .java 

 
   package com.lxx.campusstore; 
 
 
   
 
   
 
 
   
 
   import com.alibaba.fastjson.JSONArray; 
 
 
   
 
   import org.apache.ibatis.type.BaseTypeHandler; 
 
 
   
 
   import org.apache.ibatis.type.JdbcType; 
 
 
   
 
   import org.apache.ibatis.type.MappedJdbcTypes; 
 
 
   
 
   import org.apache.ibatis.type.MappedTypes; 
 
 
   
 
   
 
 
   
 
   import java.sql.CallableStatement; 
 
 
   
 
   import java.sql.PreparedStatement; 
 
 
   
 
   import java.sql.ResultSet; 
 
 
   
 
   import java.sql.SQLException; 
 
 
   
 
   
 
 
   
 
   /** 
 
 
   
 
   * Created by lixio on 2019/3/28 20:51 
 
 
   
 
   * @description 用以mysql中json格式的字段,进行转换的自定义转换器,转换为实体类的JSONArray属性 
 
 
   
 
   * MappedTypes注解中的类代表此转换器可以自动转换为的java对象 
 
 
   
 
   * MappedJdbcTypes注解中设置的是对应的jdbctype 
 
 
   
 
   */ 
 
 
   
 
   @MappedTypes(JSONArray.class) 
 
 
   
 
   @MappedJdbcTypes(JdbcType.VARCHAR) 
 
 
   
 
   public class ArrayJsonHandler extends BaseTypeHandler<JSONArray> { 
 
 
   
 
   //设置非空参数 
 
 
   
 
   @Override 
 
 
   
 
   public void setNonNullParameter(PreparedStatement ps, int i, JSONArray parameter, JdbcType jdbcType) throws SQLException { 
 
 
   
 
   ps.setString(i, String.valueOf(parameter.toJSONString())); 
 
 
   
 
   } 
 
 
   
 
   //根据列名,获取可以为空的结果 
 
 
   
 
   @Override 
 
 
   
 
   public JSONArray getNullableResult(ResultSet rs, String columnName) throws SQLException { 
 
 
   
 
   String sqlJson = rs.getString(columnName); 
 
 
   
 
   if (null != sqlJson){ 
 
 
   
 
   return JSONArray.parseArray(sqlJson); 
 
 
   
 
   } 
 
 
   
 
   return null; 
 
 
   
 
   } 
 
 
   
 
   //根据列索引,获取可以为空的结果 
 
 
   
 
   @Override 
 
 
   
 
   public JSONArray getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 
 
 
   
 
   String sqlJson = rs.getString(columnIndex); 
 
 
   
 
   if (null != sqlJson){ 
 
 
   
 
   return JSONArray.parseArray(sqlJson); 
 
 
   
 
   } 
 
 
   
 
   return null; 
 
 
   
 
   } 
 
 
   
 
   
 
 
   
 
   @Override 
 
 
   
 
   public JSONArray getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 
 
 
   
 
   String sqlJson = cs.getString(columnIndex); 
 
 
   
 
   if (null != sqlJson){ 
 
 
   
 
   return JSONArray.parseArray(sqlJson); 
 
 
   
 
   } 
 
 
   
 
   return null; 
 
 
   
 
   } 
 
 
   
 
   
 
 
   
 
   } 
 
ObjectJsonHandler.java 如下
   
 
   package com.lxx.campusstore; 
 
 
   
 
   
 
 
   
 
   import com.alibaba.fastjson.JSONObject; 
 
 
   
 
   import org.apache.ibatis.type.BaseTypeHandler; 
 
 
   
 
   import org.apache.ibatis.type.JdbcType; 
 
 
   
 
   import org.apache.ibatis.type.MappedJdbcTypes; 
 
 
   
 
   import org.apache.ibatis.type.MappedTypes; 
 
 
   
 
   
 
 
   
 
   import java.sql.CallableStatement; 
 
 
   
 
   import java.sql.PreparedStatement; 
 
 
   
 
   import java.sql.ResultSet; 
 
 
   
 
   import java.sql.SQLException; 
 
 
   
 
   
 
 
   
 
   /** 
 
 
   
 
   * Created by lixio on 2019/3/28 15:44 
 
 
   
 
   * @description 用以mysql中json格式的字段,进行转换的自定义转换器,转换为实体类的JSONObject属性 
 
 
   
 
   * MappedTypes注解中的类代表此转换器可以自动转换为的java对象 
 
 
   
 
   * MappedJdbcTypes注解中设置的是对应的jdbctype 
 
 
   
 
   */ 
 
 
   
 
   
 
 
   
 
   @MappedTypes(JSONObject.class) 
 
 
   
 
   @MappedJdbcTypes(JdbcType.VARCHAR) 
 
 
   
 
   public class ObjectJsonHandler extends BaseTypeHandler<JSONObject>{ 
 
 
   
 
   
 
 
   
 
   //设置非空参数 
 
 
   
 
   @Override 
 
 
   
 
   public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) throws SQLException { 
 
 
   
 
   ps.setString(i, String.valueOf(parameter.toJSONString())); 
 
 
   
 
   } 
 
 
   
 
   //根据列名,获取可以为空的结果 
 
 
   
 
   @Override 
 
 
   
 
   public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException { 
 
 
   
 
   String sqlJson = rs.getString(columnName); 
 
 
   
 
   if (null != sqlJson){ 
 
 
   
 
   return JSONObject.parseObject(sqlJson); 
 
 
   
 
   } 
 
 
   
 
   return null; 
 
 
   
 
   } 
 
 
   
 
   //根据列索引,获取可以为空的结果 
 
 
   
 
   @Override 
 
 
   
 
   public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 
 
 
   
 
   String sqlJson = rs.getString(columnIndex); 
 
 
   
 
   if (null != sqlJson){ 
 
 
   
 
   return JSONObject.parseObject(sqlJson); 
 
 
   
 
   } 
 
 
   
 
   return null; 
 
 
   
 
   } 
 
 
   
 
   
 
 
   
 
   @Override 
 
 
   
 
   public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 
 
 
   
 
   String sqlJson = cs.getString(columnIndex); 
 
 
   
 
   if (null != sqlJson){ 
 
 
   
 
   return JSONObject.parseObject(sqlJson); 
 
 
   
 
   } 
 
 
   
 
   return null; 
 
 
   
 
   } 
 
 
   
 
   } 
 
 

 要想 mybatis 能直接使用,接下来还得在配置文件 application.properties 下加入这两个自定义转换类的所在路径:

   
 
   #配置mybaits自定义类型转换类所在的包 
 
 
   
 
   mybatis.type-handlers-package=com.lxx.campusstore 
 
 

到这里,MyBatis 就能向普通的字段一样 对MySQL 的 json 字段数据进行增删查改了,例子如下:

resultMap 中引用自定义转换

 插入语句如下:

 
   <insert id="insert" parameterType="com.lxx.campusstore.model.Orders"> 
 
 
   
 
   insert into orders ( order_num, userid,store_id, 
 
 
   
 
   usemessage, goodslist,beizhu, all_price) 
 
 
   
 
   values (#{orderNum,jdbcType=BIGINT}, #{userid,jdbcType=VARCHAR}, #{storeId,jdbcType=INTEGER}, 
 
 
   
 
   #{usemessage,jdbcType=OTHER,typeHandler=com.lxx.campusstore.ObjectJsonHandler}, 
 
 
   
 
   #{goodslist,jdbcType=OTHER,typeHandler=com.lxx.campusstore.ArrayJsonHandler},#{beizhu,jdbcType=VARCHAR},#{allPrice,jdbcType=DOUBLE}) 
 
 
   
 
   </insert> 
 
 

 插入结果如下:(还保留着 json 格式)

查询语句如下:

  
 
   <select id="selectAll" parameterType="com.lxx.campusstore.model.Orders" resultMap="BaseResultMap"> 
 
 
   
 
   select order_id, order_num, usemessage, goodslist, beizhu, all_price, create_time 
 
 
   
 
   from orders  
 
 
   
 
   where userid = #{userid,jdbcType=VARCHAR} ORDER by create_time desc 
 
 
   
 
   </select> 
 
 

查询结果如下:(还保留着 json 格式,不用手动再转化)

到此为止,MyBatis 自定义转化类后就能自如的对 MySQL 的 json 字段进行处理了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Storm(三)Java编写第一个本地模式demo

    本地模式 在本地模式下,Storm拓扑结构运行在本地计算机的单一JVM进程上。这个模式用于开发、测试以及调试,因为这是观察所有组件如何协同工作的最简单方法。在...

    stys35
  • mapreduce如何使用本地文件 转

    stys35
  • 为什么日志要private static final

      private static final Log logger = LogFactory.getLog(SpringProperties.class);

    stys35
  • 自动化项目基类实践--视频演示

    http://mpvideo.qpic.cn/0bf2raaagaaaauaafxudrvpfbcgdaoeaaaya.f10002.mp4?dis_k=c99...

    FunTester
  • 单点登录性能测试方案

    项目登录系统升级,改为单点登录:英文全称Single Sign On。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。 之前有的统...

    FunTester
  • Android开发笔记(一百一十)使用http框架上传文件

    与文件下载相比,文件上传的场合不是很多,通常用于上传用户头像、朋友圈发布图片/视频动态等等,而且上传文件需要服务器配合,所以容易被app开发者忽略。就上传的...

    用户4464237
  • JavaWeb 图书管理系统

    图书管理系统就是利用计算机,结合互联网对图书进行结构化、自动化管理的一种软件,来提高对图书的管理效率。

    C you again 的博客
  • 爬虫(104)教你词云分析拉勾网数百个职位招聘详

    昨天我们分析了某 girl 的 QQ 空间,之后想想还是不过瘾啊,感觉还可以深度挖掘词云这个库,于是在网上找了一个实际例子又来波

    公众号---志学Python
  • SpringBoot整合Spring Data Mongodb

    爱撒谎的男孩
  • poiAndEasyExcel学习(二)

    崔笑颜

扫码关注云+社区

领取腾讯云代金券