SpringBoot mybatis-plus使用json字段实战指南

 更新时间:2024年01月31日 09:21:50   作者:张三疯不疯  
在现代应用开发中经常会使用JSON格式存储和传输数据,为了便捷地处理数据库中的JSON字段,MyBatis-Plus提供了强大的JSON处理器,这篇文章主要给大家介绍了关于SpringBoot mybatis-plus使用json字段的相关资料,需要的朋友可以参考下

1.前言

在springboot项目开发中,一般使用关系型数据库作为主库存储数据,有时候业务场景需要在既有的表结构上,扩展自定义业务信息. 这种场景下一般使用json类型存储。本文总结springboot项目中,借助mybatis-plus操作json实践方案

2.方案分析

2.1 为什么是json

JSON类型相对于传统的关系型结构,其具有数据本身对结构描述、动态扩展和嵌套等特性,能够更加自由地表示和存储数据

2.2 数据库的选择

json字段的存储依赖于底层选择的数据库, 有的关系型数据库已经支持json,比如MySQL5.7版本中,引入了JSON类型。如果没有特殊的json类型, 我们可以使用text类型存储json文本。因此要分两种情况分析. 这两种模式区别:

  • 提供json类型数据库,在查询灵活程度上更高,比如可以针对json指定key的value进行查询。text之恶能作为普通文本匹配
  • 提供json类型数据库,查询会部分依赖底层特殊查询语法. text则是通用的数据类型不存在该情况。

3. 实战

无论底层数据库使用text类型还是json类型。持久层使用mybatis-plus都要处理json与对象的映射问题。创建一个Account账号对象为例,增加一个extendJson作为存储扩展数据的json对象

@TableName(value = "account", autoResultMap = true)
public class Account {

    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private String username;

    /**
     * 注意!! 必须开启映射注解
     *
     * @TableName(autoResultMap = true)
     * <p>
     * 以下两种类型处理器,二选一 也可以同时存在
     * <p>
     * 注意!!选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包
     */
    //@TableField(typeHandler = JacksonTypeHandler.class)
    @TableField(typeHandler = FastjsonTypeHandler.class)
    private JSONObject extendJson;

    //setter/getter忽略

以上部分主要参考mp官网:https://baomidou.com/ >>字段类型处理器

3.1 使用text字段(h2数据库)

使用text字段测试json字段我们使用h2数据库进行测试

  • h2版本: 1.4.200(该版本不支持原生的json字段)

3.1.1 建表语句

使用liquibase管理建表语句

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">

    <changeSet author="demo" id="account.createTable">
        <createTable tableName="account" remarks="账号表">
            <!--设置id自增 起始位置从10000 每次加1-->
            <column name="id" remarks="账户ID" type="bigint" autoIncrement="true" incrementBy="1" startWith="10000">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <!--用户名增加唯一索引-->
            <column name="username" remarks="用户名" type="VARCHAR(32)">
                <constraints nullable="false" unique="true" uniqueConstraintName="uniq_username"/>
            </column>
            <column name="password" remarks="密码" type="VARCHAR(32)"/>
            <column name="name" remarks="姓名" type="VARCHAR(20)"/>
            <column name="sex" remarks="性别" type="CHAR(1)"/>
            <column name="phone" remarks="手机" type="VARCHAR(100)"/>
            <column name="email" remarks="邮件" type="VARCHAR(100)"/>
            <column name="create_time" remarks="创建时间" type="datetime(0)"/>
            <column name="update_time" remarks="修改时间" type="datetime(0)"/>
<!--            <column name="extend_json" remarks="拓展字段使用" type="json"/>-->
            <column name="extend_json" remarks="拓展字段使用" type="text"/>
        </createTable>
    </changeSet>

    <!--loadData:加载 csv 文件到已存在的表中-->
    <changeSet author="easy-log-demo" id="account.loadData" >
        <loadData tableName="account" file="db/liquibase/csv/account.csv" >
        </loadData>
    </changeSet>
</databaseChangeLog>

3.1.2 数据操作与查询

text存储json的数据操作与查询与普通text操作无差别

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountMapper accountMapper;

    public void createAccount(Account account) {
        account.setUsername(UUID.randomUUID().toString().replace("-", ""));
        this.accountMapper.insert(account);
    }

    public Account updateAccount(Account account) {
        this.accountMapper.updateById(account);
        return this.accountMapper.selectById(account.getId());
    }

    @Override
    public List<Account> listAll() {
        return this.accountMapper.selectList(Wrappers.emptyWrapper());
    }
}

效果:

3.2 使用json字段(mysql数据库)

3.2.1 建表语句

使用liquibase管理建表语句

  • MySQL使用版本: 大于等于5.7
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">

    <changeSet author="demo" id="account.createTable">
        <createTable tableName="account" remarks="账号表">
            <!--设置id自增 起始位置从10000 每次加1-->
            <column name="id" remarks="账户ID" type="bigint" autoIncrement="true" incrementBy="1" startWith="10000">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <!--用户名增加唯一索引-->
            <column name="username" remarks="用户名" type="VARCHAR(32)">
                <constraints nullable="false" unique="true" uniqueConstraintName="uniq_username"/>
            </column>
            <column name="password" remarks="密码" type="VARCHAR(32)"/>
            <column name="name" remarks="姓名" type="VARCHAR(20)"/>
            <column name="sex" remarks="性别" type="CHAR(1)"/>
            <column name="phone" remarks="手机" type="VARCHAR(100)"/>
            <column name="email" remarks="邮件" type="VARCHAR(100)"/>
            <column name="create_time" remarks="创建时间" type="datetime(0)"/>
            <column name="update_time" remarks="修改时间" type="datetime(0)"/>
            <column name="extend_json" remarks="拓展字段使用" type="json"/>
        </createTable>
    </changeSet>

    <!--loadData:加载 csv 文件到已存在的表中-->
    <changeSet author="easy-log-demo" id="account.loadData" >
        <loadData tableName="account" file="db/liquibase/csv/account.csv" >
        </loadData>
    </changeSet>


</databaseChangeLog>

3.2.2 数据操作与查询

mysql支持json类型因此借助特定的语法可以实现json精确查询及模糊查询

@Service
public class AccountServiceImpl implements AccountService {
    
    @Autowired
    private AccountMapper accountMapper;
    
    public void createAccount(Account account) {
        account.setUsername(UUID.randomUUID().toString().replace("-", ""));
        this.accountMapper.insert(account);
    }

    public Account updateAccount(Account account) {
        this.accountMapper.updateById(account);

        return this.accountMapper.selectById(account.getId());
    }

    /**
     * json 数据模糊查询
     * @param key extend_json 中的json的key
     * @param value extend_json 中的json的key对应value
     * @return
     */
    public List<Account> listByJsonLike(String key, String value) {
//        QueryChainWrapper<Account> queryWrapper = new QueryChainWrapper<>(this.accountMapper);
        LambdaQueryWrapper<Account> queryWrapper = Wrappers.<Account>lambdaQuery();

        //json字段模式查询
        queryWrapper.apply("JSON_EXTRACT(extend_json, '$." + key + "') LIKE {0}", "%" + value + "%")
                .ge(Account::getId, 10000);
        return this.accountMapper.selectList(queryWrapper);

    }

    /**
     * json 数据精确查询
     * @param key extend_json 中的json的key
     * @param value extend_json 中的json的key对应value
     * @return
     */
    public List<Account> listByJsonEquals(String key, String value) {
        LambdaQueryWrapper<Account> queryWrapper = Wrappers.<Account>lambdaQuery();
        //json字段精确查询
        queryWrapper.apply("JSON_EXTRACT(extend_json, '$." + key + "') = {0}", value);
        return this.accountMapper.selectList(queryWrapper);

    }

    @Override
    public List<Account> listAll() {
        return this.accountMapper.selectList(Wrappers.emptyWrapper());
    }
}
  • 效果:测试json内部字段模糊查询

4. 附录

4.1 MySQL JSON索引用法

TODO MySQLJSON索引用法介绍

4.2 mybatis-plus json查询用法

public class YourService {

    @Autowired
    private YourMapper yourMapper;

    public YourEntity getByJsonKey(String key, String value) {
        QueryWrapper&lt;YourEntity&gt; queryWrapper = Wrappers.&lt;YourEntity&gt;lambdaQuery()
                .apply("json_data-&gt;'$.key' = {0}", value);

        return yourMapper.selectOne(queryWrapper);
    }
}

在上述示例中,.apply(“json_data->‘$.key’ = {0}”, value) 中的 {0} 将会被 MyBatis-Plus 自动处理为预编译参数,保证了 SQL 的安全性。

请确保你的 MyBatis-Plus 版本支持 .apply() 方法,该方法可以用于执行自定义的 SQL 查询条件。

5. 参考文档

总结 

到此这篇关于SpringBoot mybatis-plus使用json字段的文章就介绍到这了,更多相关mybatis-plus使用json字段内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 手把手教你写Maven的archetype项目脚手架

    手把手教你写Maven的archetype项目脚手架

    本文主要介绍了Maven的archetype项目脚手架,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java并发内存模型详情

    Java并发内存模型详情

    这篇文章主要介绍了Java并发内存模型,Java是一门支持多线程执行的语言,要编写正确的并发程序,了解Java内存模型是重要前提。而了解硬件内存模型有助于理解程序的执行,下面文章就来看看详细内容吧
    2021-10-10
  • 使用lombok注解导致mybatis-plus TypeHandler失效的解决

    使用lombok注解导致mybatis-plus TypeHandler失效的解决

    这篇文章主要介绍了使用lombok注解导致mybatis-plus TypeHandler失效的解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Spring Security认证器实现过程详解

    Spring Security认证器实现过程详解

    一些权限框架一般都包含认证器和决策器,前者处理登陆验证,后者处理访问资源的控制,这篇文章主要介绍了Spring Security认证器实现过程,需要的朋友可以参考下
    2022-06-06
  • 在分布式环境下正确使用MyBatis二级缓存的最佳实践

    在分布式环境下正确使用MyBatis二级缓存的最佳实践

    缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存,我们可以避免频繁与数据库进行交互,从而提高响应速度,这篇文章主要介绍了在分布式环境下正确使用MyBatis二级缓存的最佳实践,需要的朋友可以参考下
    2025-08-08
  • SpringBoot之ApplicationRunner解析(spring容器启动完成执行的类)

    SpringBoot之ApplicationRunner解析(spring容器启动完成执行的类)

    这篇文章主要介绍了SpringBoot之ApplicationRunner解析(spring容器启动完成执行的类),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • java设计模式责任链模式原理案例详解

    java设计模式责任链模式原理案例详解

    一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现
    2021-09-09
  • 如何使用IntelliJ IDEA中的Live Templates自定义代码模板

    如何使用IntelliJ IDEA中的Live Templates自定义代码模板

    在IntelliJ IDEA中,通过使用LiveTemplates功能,可以实现快速编码和自定义代码模板,例如,输入“main”可以自动补全主函数结构,“sout”可以补全输出语句,用户可以通过设置中的LiveTemplates选项查看和定义快捷模板,支持使用分组管理和参数化模板内容,适应复杂的编码需求
    2024-11-11
  • 解决mapper接口无法映射mapper.xml的问题

    解决mapper接口无法映射mapper.xml的问题

    这篇文章主要介绍了解决mapper接口无法映射mapper.xml的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • 浅谈Android开发中项目的文件结构及规范化部署建议

    浅谈Android开发中项目的文件结构及规范化部署建议

    这篇文章主要介绍了Android开发中项目的文件结构及规范化部署建议,组织好代码文件的结构有利于维护团队合作的效率,需要的朋友可以参考下
    2016-03-03

最新评论