MyBatis Plus 数据库字段加密处理

这篇具有很好参考价值的文章主要介绍了MyBatis Plus 数据库字段加密处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.场景介绍

  • 当项目开发到一半,可能突然客户会要求对数据库里面比如手机号、身份证号的字段进行加密;
  • 在保证开发最快、影响范围最小的情况下,我们需要选择一种介于数据库和代码之间的工具来帮我们实现自动加解密;

2.Maven依赖

<!-- mybatis-plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>

<!-- mybatis的分页插件 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.11</version>
    <!-- pagehelper 包含该依赖存在版本冲突,因此不建议和 mp 一起混用 -->
    <exclusions>
        <exclusion>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2.AESUtil.java 加解密工具类

这里我们选用AES对称加密算法,因为它是可逆算法。

AES加密介绍: https://blog.csdn.net/qq_33204709/article/details/126930720

具体实现代码如下:

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密工具类
 *
 * @author ACGkaka
 * @since 2021-06-18 19:11:03
 */
public class AESUtil {
    /**
     * 日志相关
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(AESUtil.class);
    /**
     * 编码
     */
    private static final String ENCODING = "UTF-8";
    /**
     * 算法定义
     */
    private static final String AES_ALGORITHM = "AES";
    /**
     * 指定填充方式
     */
    private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding";
    private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS5Padding";
    /**
     * 偏移量(CBC中使用,增强加密算法强度)
     */
    private static final String IV_SEED = "1234567812345678";

    /**
     * AES加密
     * @param content 待加密内容
     * @param aesKey  密码
     * @return
     */
    public static String encrypt(String content, String aesKey){
        if(StringUtils.isBlank(content)){
            LOGGER.info("AES encrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置加密算法,生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
                //选择加密
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                //根据待加密内容生成字节数组
                byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
                //返回base64字符串
                return Base64Utils.encodeToString(encrypted);
            } catch (Exception e) {
                LOGGER.info("AES encrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
            LOGGER.info("AES encrypt: the aesKey is null or error!");
            return null;
        }
    }

    /**
     * 解密
     * 
     * @param content 待解密内容
     * @param aesKey  密码
     * @return
     */
    public static String decrypt(String content, String aesKey){
        if(StringUtils.isBlank(content)){
            LOGGER.info("AES decrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置解密算法,生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
                //选择解密
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);

                //先进行Base64解码
                byte[] decodeBase64 = Base64Utils.decodeFromString(content);

                //根据待解密内容进行解密
                byte[] decrypted = cipher.doFinal(decodeBase64);
                //将字节数组转成字符串
                return new String(decrypted, ENCODING);
            } catch (Exception e) {
                LOGGER.info("AES decrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
            LOGGER.info("AES decrypt: the aesKey is null or error!");
            return null;
        }
    }

    /**
     * AES_CBC加密
     * 
     * @param content 待加密内容
     * @param aesKey  密码
     * @return
     */
    public static String encryptCBC(String content, String aesKey){
        if(StringUtils.isBlank(content)){
            LOGGER.info("AES_CBC encrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置加密算法,生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
                //偏移
                IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
                //选择加密
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
                //根据待加密内容生成字节数组
                byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
                //返回base64字符串
                return Base64Utils.encodeToString(encrypted);
            } catch (Exception e) {
                LOGGER.info("AES_CBC encrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
            LOGGER.info("AES_CBC encrypt: the aesKey is null or error!");
            return null;
        }
    }

    /**
     * AES_CBC解密
     * 
     * @param content 待解密内容
     * @param aesKey  密码
     * @return
     */
    public static String decryptCBC(String content, String aesKey){
        if(StringUtils.isBlank(content)){
            LOGGER.info("AES_CBC decrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置解密算法,生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                //偏移
                IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
                //选择解密
                cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

                //先进行Base64解码
                byte[] decodeBase64 = Base64Utils.decodeFromString(content);

                //根据待解密内容进行解密
                byte[] decrypted = cipher.doFinal(decodeBase64);
                //将字节数组转成字符串
                return new String(decrypted, ENCODING);
            } catch (Exception e) {
                LOGGER.info("AES_CBC decrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
            LOGGER.info("AES_CBC decrypt: the aesKey is null or error!");
            return null;
        }
    }

    public static void main(String[] args) {
        // AES支持三种长度的密钥:128位、192位、256位。
        // 代码中这种就是128位的加密密钥,16字节 * 8位/字节 = 128位。
        String random = RandomStringUtils.random(16, "abcdefghijklmnopqrstuvwxyz1234567890");
        System.out.println("随机key:" + random);
        System.out.println();

        System.out.println("---------加密---------");
        String aesResult = encrypt("测试AES加密12", random);
        System.out.println("aes加密结果:" + aesResult);
        System.out.println();

        System.out.println("---------解密---------");
        String decrypt = decrypt(aesResult, random);
        System.out.println("aes解密结果:" + decrypt);
        System.out.println();


        System.out.println("--------AES_CBC加密解密---------");
        String cbcResult = encryptCBC("测试AES加密12456", random);
        System.out.println("aes_cbc加密结果:" + cbcResult);
        System.out.println();

        System.out.println("---------解密CBC---------");
        String cbcDecrypt = decryptCBC(cbcResult, random);
        System.out.println("aes解密结果:" + cbcDecrypt);
        System.out.println();
    }
}

3.字段处理类

import com.demo.util.AESUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * <p> @Title MyEncryptTypeHandler
 * <p> @Description 字段加密处理
 *
 * @author ACGkaka
 * @date 2023/2/21 17:20
 */
public class MyEncryptTypeHandler extends BaseTypeHandler<String> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, AESUtil.defaultEncrypt(parameter));
    }

    @Override
    public String getNullableResult(ResultSet rs, String column) throws SQLException {
        return AESUtil.defaultDecrypt(rs.getString(column));
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return AESUtil.defaultDecrypt(rs.getString(columnIndex));
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return AESUtil.defaultDecrypt(cs.getString(columnIndex));
    }
}

4.修改 MyBatis Plus 查询

4.1 修改表对应实体类

设置 @TableName 注解的 autoResultMap 为 true,默认 false。

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * 用户表
 *
 * @author ACGkaka
 * @date 2023/2/21 17:20
 */
@Data
@TableName(value = "t_user_info", autoResultMap = true)
public class UserInfo implements Serializable {}

4.2 修改加密字段对应属性

设置 @TableField 注解的 typeHandlerMyEncryptTypeHandler.class

import com.demo.encrypt.MyEncryptTypeHandler;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * 用户表
 *
 * @author ACGkaka
 * @date 2023/2/21 17:20
 */
@Data
@TableName(value = "t_user_info", autoResultMap = true)
public class UserInfo implements Serializable {
    /**
     * 手机号码
     */
    @TableField(value = "PHONE", typeHandler = MyEncryptTypeHandler.class)
    private String phone;
}

4.3 修改 xml 使用 ResultMap

1)创建 ResultMap 映射,指定 typeHandler

2)查询语句使用 ResultMap 返回。

<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.demo.model.UserInfo">
    <id column="ID" property="id" />
    <result column="ACCOUNT" property="staffCode" />
    <result column="PHONE" property="phone" typeHandler="com.demo.encrypt.MyEncryptTypeHandler" />
</resultMap>

<!-- 查询全部 -->
<select id="findAll" resultMap="BaseResultMap">
    SELECT * FROM t_user_info
</select>

4.4 修改 xml 中 el 表达式

设置好 4.1 和 4.2 就可以保证

修改前:

<!-- 更新手机号 -->
<update id="updatePhoneById">
    update t_user_info set phone = #{phone} where id = #{id}
</update>

<!-- 根据手机号查询 -->
<select id="findByPhone" resultMap="BaseResultMap">
    SELECT * FROM t_user_info where phone = #{phone}
</select>

修改后:

<!-- 更新手机号 -->
<update id="updatePhoneById">
    update t_user_info set phone = #{phone, typeHandler=com.demo.encrypt.MyEncryptTypeHandler} where id = #{id}
</update>

<!-- 根据手机号查询 -->
<select id="findByPhone" resultMap="BaseResultMap">
    SELECT * FROM t_user_info where phone = #{phone, typeHandler=com.demo.encrypt.MyEncryptTypeHandler}
</select>

5.测试结果

由于测试内容较多,这里先直接展示测试结果,具体测试示例可以看 补充:测试实例

操作 实现方式 入参 测试结果
SELECT 原生SQL 非加密字段 出参解密成功
SELECT QueryWrapper 非加密字段 出参解密成功
SELECT 原生SQL 加密字段 入参加密成功
SELECT QueryWrapper 加密字段 入参加密失败
UPDATE 原生SQL 加密字段 入参加密成功
UPDATE UpdateWrapper 加密字段 入参加密失败
UPDATE LambdaUpdateWrapper 加密字段 入参加密成功
UPDATE updateById 加密字段 入参加密成功
INSERT Service 加密字段 入参加密成功

说明:

  • 官方的解答是 QueryWrapper、UpdateWrapper 底层是通过 @Param 来实现的,目前没有做到入参支持 typeHandler,如果做的话会影响性能。
  • LambdaUpdateWrapper 要求 MyBatis-Plus 版本为 3.5.3,PageHelper 也需要升级为 5.1.11,但是升级之后 PageHelper 分页不好使了,待优化。(升级后依赖参考 补充:2.3)

6.MyBatis Plus 缺陷

  • QueryWrapper 不支持入参加密;

  • UpdateWrapper 不支持入参加密;

  • 加密字段不支持模糊查询。

7.历史数据加密处理程序

@Override
public void encryptUser() {
    // 加密 用户信息
    int count = this.count();
    int pageSize = 1000;
    int pageCount = count / pageSize + 1;
    // 必须用唯一且非空字段进行排序,否则 pageHelper 查出来的数据可能会有重复。
    QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().orderByAsc("id");
    for (int i = 0; i < pageCount; i++) {
        log.info(">>>>>>>>>> 【INFO】加密用户信息,当前页数:{},总页数:{}", i + 1, pageCount);
        PageHelper.startPage(i + 1, pageSize);
        List<UserInfo> users = this.list(queryWrapper);
        new PageInfo<>(users);
        users.parallelStream().forEach(o -> {
            // 解密重复加密手机号
            while (AESUtil.defaultDecrypt(o.getPhoneNumber()) != null) {
                o.setPhoneNumber(AESUtil.defaultDecrypt(o.getPhoneNumber()));
            }
            // 解密重复加密身份证号
            while (AESUtil.defaultDecrypt(o.getIdCard()) != null) {
                o.setIdCard(AESUtil.defaultDecrypt(o.getIdCard()));
            }
        });
        this.updateBatchById(users);
    }
}

一般手机号AES加密后长度为32,我们可以根据这点通过SQL检查加密情况:

select '未加密数量' state, COUNT(*) from t_user_info where length(phone_number) < 32 
union all
select '重复加密数量' state, COUNT(*)  from t_user_info where length(phone_number) > 32;

补充:测试实例

1 查询测试

1.1 查询信息,SQL实现
@Test
public void getUserInfoTest1() {
    UserInfo userInfo = userInfoService.findByAccount("testAccount");
    System.out.println("userInfo:" + userInfo);
    System.out.println("phone:" + userInfo.getPhone());
}

测试结果:出参解密成功

1.2 查询信息,QueryWrapper实现
@Test
public void getUserInfoTest2() {
    QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
    wrapper.eq("account", "testAccount");
    List<UserInfo> users = userInfoService.list(wrapper);
    System.out.println("userInfo:" + users);
    System.out.println("phone:" + users.get(0).getPhone());
}

测试结果:出参解密成功

1.3 查询信息,根据加密字段查询,SQL实现
@Test
public void getUserInfoTest3() {
    UserInfo user = userInfoService.findByPhone("13888888888");
    System.out.println("userInfo:" + user);
    System.out.println("phone:" + user.getPhone());
}

(注意:入参需要使用el表达式指定 typeHandler)

测试结果:入参加密成功

1.4 查询信息,根据加密字段查询,QueryWrapper实现
@Test
public void getUserInfoTest3() {
    QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
    wrapper.lambda().eq(UserInfo::getPhone, "13888888888");
    List<UserInfo> users = userInfoService.list(wrapper);
    System.out.println("userInfo:" + users);
    System.out.println("phone:" + users.get(0).getPhone());
}

测试结果:入参加密失败,QueryWrapper底层使用 @Param 实现,无法像 SQL 实现一样指定 typeHandler。

2.测试更新

2.1 更新信息,SQL实现
@Test
public void updateUserInfoTest1() {
    userInfoService.updatePhoneByAccount("testAccount", "13888888888");
}

测试结果:入参加密成功

2.2 更新信息,UpdateWrapper实现
@Test
public void updateUserInfoTest2() {
    UpdateWrapper<UserInfo> wrapper = new UpdateWrapper<>();
    wrapper.set("phone", "13888888888");
    wrapper.eq("account", "testAccount");
    userInfoService.update(wrapper);
    getUserInfoTest1();
}

测试结果:入参加密失败,UpdateWrapper底层使用 @Param 实现,无法像 SQL 实现一样指定 typeHandler。

2.3 更新信息,LambdaUpdateWrapper实现
@Test
public void updateUserInfoTest3() {
    LambdaUpdateWrapper<UserInfo> wrapper = Wrappers.<UserInfo>lambdaUpdate()
            .set(UserInfo::getPhone, "13888888888", "typeHandler=com.demo.encrypt.MyEncryptTypeHandler");
    wrapper.eq(UserInfo::getAccount, "testAccount");
    userInfoService.update(wrapper);
    getUserInfoTest1();
}

测试结果:入参加密成功(3.5.3支持,但是升级之后 PageHelper 分页不好使了,待优化)

升级后依赖:

<!-- mybatis-plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3</version>
</dependency>

<!-- mybatis的分页插件 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.11</version>
    <!-- pagehelper 包含该依赖存在版本冲突,因此不建议和 mp 一起混用 -->
    <exclusions>
        <exclusion>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
        </exclusion>
    </exclusions>
</dependency>
2.4 更新信息,updateById实现
@Test
public void updateUserInfoTest4() {
    UserInfo userInfo = userInfoService.findByAccount("testAccount");
    userInfo.setPhone("13888888888");
    userInfoService.updateById(userInfo);
}

测试结果:入参加密成功

3.测试插入

7.3.1 插入信息,SQL实现
@Test
public void insertUserInfoTest1() {
    UserInfo userInfo = userInfoService.findByAccount("testAccount");
    userInfo.setAccount("testAccount_002");
    userInfo.setPhone("13888888888");
    userInfoService.save(userInfo);
    UserInfo newUserInfo = userInfoService.findByAccount("testAccount_002");
    System.out.println("userInfo:" + newUserInfo);
    System.out.println("phone:" + newUserInfo.getPhone());
}

测试结果:入参加密成功

3.2 插入信息,Service实现
@Test
public void insertUserInfoTest1() {
    UserInfo userInfo = userInfoService.findByAccount("testAccount");
    userInfo.setAccount("testAccount_002");
    userInfo.setPhone("13888888888");
    userInfoService.save(userInfo);
    UserInfo newUserInfo = userInfoService.findByAccount("testAccount_002");
    System.out.println("userInfo:" + newUserInfo);
    System.out.println("phone:" + newUserInfo.getPhone());
}

测试结果:入参加密成功

整理完毕,完结撒花~





参考地址:

1.mybaits plus 字段加密与解密,https://blog.csdn.net/qq_21134059/article/details/121752978

2.mybatis plus 官方问题页面,https://github.com/baomidou/mybatis-plus/issues

3.更新时自定义的TypeHandler不生效,https://github.com/baomidou/mybatis-plus/issues/794

4.lambdaUpdate() 无法更新Json对象字段,https://github.com/baomidou/mybatis-plus/issues/5031

5.LambdaUpdateWrapper不支持自定义BaseTypeHandler,https://github.com/baomidou/mybatis-plus/issues/3317文章来源地址https://www.toymoban.com/news/detail-465831.html

到了这里,关于MyBatis Plus 数据库字段加密处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot mybatis-plus数据库超时配置

    超时异常 写XML 写法,单位秒 Mapper类写法,单位秒 超时异常 整个事务的超时时间,单位是秒。 它的原理大致是事务启动时,事务上下文会计算一个到期时间deadLine(当前时间+超时时间),当mybatis - prepareStatement时,会调用 SpringManagedTransaction 的getTimeOut,该方法会计算事务剩

    2024年02月03日
    浏览(41)
  • Sql Server数据库实现表中字段的列加密研究

            去年6月份的时候做过一个系统,要对里面的一些敏感字段进行一下加密。Sqlserver列加密可以参考官方文档:SQL Server 技术文档 - SQL Server | Microsoft Learn。主要看下来有三种加密方法:1、利用证书对数据进行加密和解密。2、利用非对称密钥对数据进行加密和解密。3、利

    2024年02月05日
    浏览(74)
  • Spring Boot + MyBatis-Plus实现数据库读写分离

    🎉Spring Boot + MyBatis-Plus实现数据库读写分离 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:架构设计 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水平有限,如果文中出现错误,希望

    2024年02月05日
    浏览(53)
  • 问题解决:使用Mybatis Plus的Mapper插入达梦数据库报“数据溢出”错误

    使用Mybatis Plus的Mapper插入达梦数据库报“数据溢出”错误 问题描述 在进行批量插入中,抛出异常为数据溢出 插入方法:this.baseMapper.insertBatchSomeColumn() 抛出异常:数据溢出 对失败的数据进行循环,尝试使用单个插入的方法,同样抛出异常为数据溢出 插入方法:this.baseMapper

    2024年02月07日
    浏览(39)
  • MyBatis-Plus 查询PostgreSQL数据库jsonb类型保持原格式

    在这篇文章,我们保存了数据库的jsonb类型:MyBatis-Plus 实现PostgreSQL数据库jsonb类型的保存与查询 这篇文章介绍了模糊查询json/jsonb类型:PostgreSQL 查询json/jsonb是否存在某个片段 在模糊查询json/jsonb之前,我们得拿到正确的json/jsonb片段,比如我们模糊查询好几个连着的键值对,

    2024年02月15日
    浏览(41)
  • 【Java】Mybatis查询数据库返回JSON格式的字段映射到实体类属性

    今天遇到了一个bug,大概就是数据库(Mysql)中有一个 type 类型字段,数据类型为json,大概是这样的:[“苹果”,“香蕉”,“葡萄”]的数据格式,这个bug的问题所在呢就是查询后这个json格式的数据无法映射到我们实体类的属性上,解决方案如下: 实体类的配置: @TableField

    2024年02月15日
    浏览(33)
  • Mybatis-Plus处理Mysql Json类型字段

    Mysql 5.7.8开始支持Json对象和Json数组,但在Mysql 8版本中使用Json性能更佳。 使用Json格式的好处: 无须预定义字段:字段可以无限拓展,避免了ALTER ADD COLUMN的操作,使用更加灵活。 处理稀疏字段:避免了稀疏字段的NULL值,避免冗余存储。 支持索引:相比于字符串格式的JSON,

    2024年02月03日
    浏览(39)
  • 【数据库】Sql Server数据迁移,处理自增字段赋值

    给自己一个目标,然后坚持一段时间,总会有收获和感悟! 在实际项目开发中,如果遇到高版本导入到低版本,或者低版本转高版本,那么就会出现版本不兼容无法导入,此时通过程序遍历创建表和添加数据方式可以解决 在 SQL Server 中,数据迁移是常见的场景之一。 以下是

    2024年02月08日
    浏览(43)
  • spring boot shardingsphere mybatis-plus druid mysql 搭建mysql数据库读写分离架构

    ##关于window mysql主从搭建简单教程 传送门 window mysql5.7 搭建主从同步环境-CSDN博客 ##父pom.xml ##模块pom.xml ##yml配置 ##mapper.xml ##TestMapper ##TestService ##TestController ##浏览器访问 ##数据库

    2024年01月21日
    浏览(52)
  • Spring Boot使用jasypt处理数据库账号密码等数据加密问题

    在我们业务场景中,项目中的application.yml 配置文件比如数据库账号密码,的各种链接的username,password的值都是明文的,存在一定的安全隐患,可以使用jasypt 加密框架的方式进行明文加密,进而使得我们项目更加安全 注意这里排除了mybatis-plus的包可能是项目中有冲突依赖,

    2024年02月06日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包