mysql中json类型字段用法

Posted 普通网友

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql中json类型字段用法相关的知识,希望对你有一定的参考价值。

前言

mysql从5.7.8版本开始原生支持了JSON类型数据,同时可以对JSON类型字段中的特定的值进行查询和更新等操作,通过增加JSON类型的属性可以大大的提高我们在mysql表中存储的数据的拓展性,无需每次新增字段时都进行表结构的调整,下面我们不深入讲解底层的实现原理,我们主要来梳理一下我们在日常工作中使用实践

基本环境

  • mysql版本:8.0.28

  • springboot版本: 2.2.2

  • 测试表结构:

    CREATE TABLE t_json (
    id int unsigned NOT NULL AUTO_INCREMENT,
    name varchar(100) DEFAULT NULL,
    json_obj json DEFAULT NULL,
    create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

  • 表结构对应的实体类:

    @Data
    public class JsonTest
    private Integer id;
    private String name;
    private JsonObj jsonObj;

  • JsonObj类

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class JsonObj
    private String data;
    private int age;

自定义格式转换类:转换过程通过fastjson来进行,需依赖fastjson对应的pom文件

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedTypes(String.class)
@Slf4j
public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> 
    private Class<T> clazz;

    public JsonTypeHandler(Class<T> clazz) 
        if (clazz == null) 
            throw new IllegalArgumentException("Type argument cannot be null");
        
        this.clazz = clazz;
    

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException 
        ps.setString(i, this.toJson(parameter));
    

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException 
        return this.toObject(rs.getString(columnName), clazz);
    

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException 
        return this.toObject(rs.getString(columnIndex), clazz);
    

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException 
        return this.toObject(cs.getString(columnIndex), clazz);
    

    private String toJson(T object) 
            return JSON.toJSONString(object);
    

    private T toObject(String content, Class<?> clazz) 
        if (content != null && !content.isEmpty()) 
                return (T) JSON.parseObject(content, clazz);
         else 
            return null;
        
    


JSON类型字段常用操作

插入JSON类型数据

在项目开发中,表结构中的json字段可以用JSONObject这样的比较灵活的方式来传递,但是这样的方式有一个比较大的问题就是我们在获得这个结构后无法很直观的确定json字段中存储的数据,比较好的一种方式是我们将表结构中的json类型的字段以自定义的类来存储,这样我们再存取这个类对应的对象的时候,就可以明确的知道数据库中对应的json字段到底存储的是一些什么样的key,如果需要进行调整的话,我们只需要在该类中新增新的字段即可,完全无需对数据库进行任何的调整。这样的存储方式我们再插入和查询该字段的时候需要指定一个指定的数据类型转换的类来对数据库中的JSON格式数据和我们在项目中的自定义类进行转换的类,具体如下图所示:

@Mapper
public interface JsonMapper 

    @Insert(
            "insert into t_json set name= #name, json_obj = #jsonObj ,jdbcType=OTHER, typeHandler=cn.example.eureka.service.one.config.JsonTypeHandler"
    )
    int insert(JsonTest json);

查询JSON类型数据

在进行查询时,由于也需要进行json格式数据和自定义类的转换,所以我们需要指定对应的json字段和转换的工具类,通过@Result注解来进行指定

@Mapper
public interface JsonMapper 


    @Select("<script>",
            "select * from t_json where id = #id",
    "</script>")
    @Results(
            @Result(column = "json_obj", property = "jsonObj", typeHandler = JsonTypeHandler.class)
    )
    JsonTest getById(Integer id);


更新JSON类型数据中的特定字段

进行指定字段的更新的话,有两种方式可以采用,一种方式是先将该json格式字段中的所有数据都取出,然后通过修改当前对象的值,然后整个json格式字段set进去;第二种方式直接通过json格式的特定SQL语法来进行指定key的更新;下面的例子里面我们分别根据这两种不同的模式进行更新操作

//模式一:整体更新整个json字段
@Update(
            "update t_json set json_obj = #jsonObj ,jdbcType=OTHER, typeHandler=cn.example.eureka.service.one.config.JsonTypeHandler where id = #id"
    )
    int update(JsonTest jsonTest);


//模式二:只更新json字段中的特定key
@Update(
            "update t_json set json_obj = JSON_SET(json_obj, '$.data', #data) where id = #id"
    )
    int updateData(@Param("id") Integer id, @Param("data") String data);
说明

和上面的JSON_SET同样可以用于修改的操作函数还有:JSON_INSERT、 JSON_REPLACE 、 JSON_REMOVE等,下面简单说一下这几个函数的不同

  • JSON_INSERT : json字段中的key不存在才会修改
  • JSON_REPLACE : json字段中的key存在才会修改
  • JSON_SET : json字段中的可以不管是否存在都会修改
  • JSON_REMOVE : 移除json字段中的指定key

如下所示JSON_REMOVE的用法:

@Update(
            "update t_json set json_obj = JSON_REMOVE(json_obj, '$.age') where id = #id"
    )
    int removeAge(@Param("id") Integer id);

匹配JSON类型数据中的特定字段

//模式一
@Select(
            "select * from t_json where json_obj -> '$.age' = #age"
    )
    @Results(
            @Result(column = "json_obj", property = "jsonObj", typeHandler = JsonTypeHandler.class)
    )
    List<JsonTest> getByAge(int age);
    
    
//模式二
@Select(
            "select * from t_json where JSON_EXTRACT(json_obj , '$.data') = #data"
    )
    @Results(
            @Result(column = "json_obj", property = "jsonObj", typeHandler = JsonTypeHandler.class)
    )
    List<JsonTest> getByData(String data);

结语

今天先写这么多,接下来再不断补充

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

mysql json数据类型

一、MYSQL中json类型的数据处理

​ MYSQL 5.7.8中引入了json字段类型

json字段的操作方法

初始化数据
-- 创建表 含有字段id、aley, 其中aley为json类型
mysql> show create table test;
+-------+----------------------------------+
| Table | Create Table  
+-------+----------------------------------+
| test  | CREATE TABLE `test` (
  `aley` json DEFAULT NULL,
  `id` int NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 |
+-------+---------------------------------+
1 row in set (0.00 sec)

-- 插入数据
mysql> insert into test values (\'{"name":"aley","age":18}\', 1),(\'{"name":"szx","age":30}\',2),(\'{"name":"wwj","age":35}\', 3);
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from test;
+-----------------------------+----+
| aley                        | id |
+-----------------------------+----+
| {"age": 18, "name": "aley"} |  1 |
| {"age": 30, "name": "szx"}  |  2 |
| {"age": 35, "name": "wwj"}  |  3 |
+-----------------------------+----+
3 rows in set (0.00 sec)
json_valid()

json_valid可以判断字段是否是json类型,如果是则返回1 不是返回0

mysql> select json_valid(aley) from test;
+------------------+
| json_valid(aley) |
+------------------+
|                1 |
|                1 |
|                1 |
+------------------+
3 rows in set (0.00 sec)

mysql> select json_valid(9);
+---------------+
| json_valid(9) |
+---------------+
|             0 |
+---------------+
1 row in set (0.00 sec)
json_extract()

使用json_extract获取json内的数据,json_extract需要两个参数, 第一个参数是字段名,第二个参数是需要取的json值,$表示根节点,$.age就是根节点下的age值,如果是多层json可以一直接着后面.key

mysql> select json_extract(aley, "$.age") as age from test;
+------+
| age  |
+------+
| 18   |
| 30   |
| 35   |
+------+
3 rows in set (0.00 sec)
json_keys()

使用json_keys可以查看最上层的所有key, 如果是多层的json只会返回传入的最上层的key

mysql> select json_keys(aley) from test;
+-----------------+
| json_keys(aley) |
+-----------------+
| ["age", "name"] |
| ["age", "name"] |
| ["age", "name"] |
+-----------------+
3 rows in set (0.01 sec)

mysql> select json_keys(\'{"a":{"b":1}}\');
+----------------------------+
| json_keys(\'{"a":{"b":1}}\') |
+----------------------------+
| ["a"]                      |
+----------------------------+
1 row in set (0.00 sec)

mysql> select json_keys(json_extract(\'{"a":{"b":1}}\', \'$.a\'));
+-------------------------------------------------+
| json_keys(json_extract(\'{"a":{"b":1}}\', \'$.a\')) |
+-------------------------------------------------+
| ["b"]                                           |
+-------------------------------------------------+
1 row in set (0.02 sec)
json_type()

使用json_type可以查看类型

mysql> select json_type(\'[1,2,3]\');
+----------------------+
| json_type(\'[1,2,3]\') |
+----------------------+
| ARRAY                |
+----------------------+
1 row in set (0.00 sec)

mysql> select json_type(\'{"a":1}\');
+----------------------+
| json_type(\'{"a":1}\') |
+----------------------+
| OBJECT               |
+----------------------+
1 row in set (0.00 sec)

mysql> select json_type(\'"a"\');
+------------------+
| json_type(\'"a"\') |
+------------------+
| STRING           |
+------------------+
1 row in set (0.00 sec)
json_array()

使用json_array可以获得一个json数组,传入一个空的或者多个值,返回这些值的json数组

mysql> select json_array("a", "b", now());
+------------------------------------------+
| json_array("a", "b", now())              |
+------------------------------------------+
| ["a", "b", "2021-06-08 10:36:50.000000"] |
+------------------------------------------+
1 row in set (0.00 sec)
json_extract

使用json_extract可以获取json里面的值

mysql> select json_extract(aley, \'$.name\') from test;
+------------------------------+
| json_extract(aley, \'$.name\') |
+------------------------------+
| "aley"                       |
| "szx"                        |
| "wwj"                        |
+------------------------------+
3 rows in set (0.00 sec)

注: json_extract 第一个参数是json数据, 第二个参数是取json值的路径, $为根节点。后面跟json的键(例:json为 {"a":1}, 要取a的值 $.a)

​ 如果是多层嵌套的json可以接着点,如果是json的值是数组可以在键后面跟索引取对应的值

mysql> select json_extract(\'{"a": [1,2,3]}\', \'$.a\');
+---------------------------------------+
| json_extract(\'{"a": [1,2,3]}\', \'$.a\') |
+---------------------------------------+
| [1, 2, 3]                             |
+---------------------------------------+
1 row in set (0.00 sec)

mysql> select json_extract(\'{"a": [1,2,3]}\', \'$.a[*]\');
+------------------------------------------+
| json_extract(\'{"a": [1,2,3]}\', \'$.a[*]\') |
+------------------------------------------+
| [1, 2, 3]                                |
+------------------------------------------+
1 row in set (0.00 sec)

mysql> select json_extract(\'{"a": [1,2,3]}\', \'$.a[0]\');
+------------------------------------------+
| json_extract(\'{"a": [1,2,3]}\', \'$.a[0]\') |
+------------------------------------------+
| 1                                        |
+------------------------------------------+
1 row in set (0.00 sec)

mysql> select json_extract(\'{"a": [1,2,3]}\', \'$.a[1]\');
+------------------------------------------+
| json_extract(\'{"a": [1,2,3]}\', \'$.a[1]\') |
+------------------------------------------+
| 2                                        |
+------------------------------------------+
1 row in set (0.00 sec)

以上是关于mysql中json类型字段用法的主要内容,如果未能解决你的问题,请参考以下文章

mysql json数据类型

mysql json字段中数值的加减

MySQL5.7支持的json字段查询

mysqljson存储被截断,没有报错

mysql数据库中,如何对json数据类型的值进行修改?通过json_set函数对json字段值进行修改?

MySQL JSON类型字段的查找与更新