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: "张三"
}
}
而我想把 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 字段进行处理了。