最近学习过程中遇到一个需要将订单数据存入数据库需求,项目是使用 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: "张三"
}
}
而我想把 goods 、usemessage 这两个比较复杂的数据当成分别一个字段去处理,不想拆分里面的字段,之前没有将 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 来转化,行吧,那就写呗。不过之前要看看 goods 、usemessage 这两个是有区别的,所以我分别转成了 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 字段进行处理了。
这就是留下一个学习笔记,如果对你有一点点帮助的话,就点个赞咯!!
如有错误欢迎大家指正,一起学习进步嘻嘻嘻!!