国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

MyBatis Plus 數(shù)據(jù)庫字段加密處理

這篇具有很好參考價值的文章主要介紹了MyBatis Plus 數(shù)據(jù)庫字段加密處理。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1.場景介紹

  • 當(dāng)項目開發(fā)到一半,可能突然客戶會要求對數(shù)據(jù)庫里面比如手機號、身份證號的字段進(jìn)行加密;
  • 在保證開發(fā)最快、影響范圍最小的情況下,我們需要選擇一種介于數(shù)據(jù)庫和代碼之間的工具來幫我們實現(xiàn)自動加解密;

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

具體實現(xiàn)代碼如下:

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 {
    /**
     * 日志相關(guān)
     */
    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 待加密內(nèi)容
     * @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 {
                //對密碼進(jìn)行編碼
                byte[] bytes = aesKey.getBytes(ENCODING);
                //設(shè)置加密算法,生成秘鑰
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/補碼方式"
                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
                //選擇加密
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                //根據(jù)待加密內(nèi)容生成字節(jié)數(shù)組
                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 待解密內(nèi)容
     * @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 {
                //對密碼進(jìn)行編碼
                byte[] bytes = aesKey.getBytes(ENCODING);
                //設(shè)置解密算法,生成秘鑰
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/補碼方式"
                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
                //選擇解密
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);

                //先進(jìn)行Base64解碼
                byte[] decodeBase64 = Base64Utils.decodeFromString(content);

                //根據(jù)待解密內(nèi)容進(jìn)行解密
                byte[] decrypted = cipher.doFinal(decodeBase64);
                //將字節(jié)數(shù)組轉(zhuǎn)成字符串
                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 待加密內(nèi)容
     * @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 {
                //對密碼進(jìn)行編碼
                byte[] bytes = aesKey.getBytes(ENCODING);
                //設(shè)置加密算法,生成秘鑰
                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);
                //根據(jù)待加密內(nèi)容生成字節(jié)數(shù)組
                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 待解密內(nèi)容
     * @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 {
                //對密碼進(jìn)行編碼
                byte[] bytes = aesKey.getBytes(ENCODING);
                //設(shè)置解密算法,生成秘鑰
                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);

                //先進(jìn)行Base64解碼
                byte[] decodeBase64 = Base64Utils.decodeFromString(content);

                //根據(jù)待解密內(nèi)容進(jìn)行解密
                byte[] decrypted = cipher.doFinal(decodeBase64);
                //將字節(jié)數(shù)組轉(zhuǎn)成字符串
                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字節(jié) * 8位/字節(jié) = 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加密結(jié)果:" + aesResult);
        System.out.println();

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


        System.out.println("--------AES_CBC加密解密---------");
        String cbcResult = encryptCBC("測試AES加密12456", random);
        System.out.println("aes_cbc加密結(jié)果:" + cbcResult);
        System.out.println();

        System.out.println("---------解密CBC---------");
        String cbcDecrypt = decryptCBC(cbcResult, random);
        System.out.println("aes解密結(jié)果:" + 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 修改表對應(yīng)實體類

設(shè)置 @TableName 注解的 autoResultMap 為 true,默認(rèn) 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 修改加密字段對應(yīng)屬性

設(shè)置 @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)創(chuàng)建 ResultMap 映射,指定 typeHandler;

2)查詢語句使用 ResultMap 返回。

<!-- 通用查詢映射結(jié)果 -->
<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>

<!-- 查詢?nèi)?-->
<select id="findAll" resultMap="BaseResultMap">
    SELECT * FROM t_user_info
</select>

4.4 修改 xml 中 el 表達(dá)式

設(shè)置好 4.1 和 4.2 就可以保證

修改前:

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

<!-- 根據(jù)手機號查詢 -->
<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>

<!-- 根據(jù)手機號查詢 -->
<select id="findByPhone" resultMap="BaseResultMap">
    SELECT * FROM t_user_info where phone = #{phone, typeHandler=com.demo.encrypt.MyEncryptTypeHandler}
</select>

5.測試結(jié)果

由于測試內(nèi)容較多,這里先直接展示測試結(jié)果,具體測試示例可以看 補充:測試實例

操作 實現(xiàn)方式 入?yún)?/th> 測試結(jié)果
SELECT 原生SQL 非加密字段 出參解密成功
SELECT QueryWrapper 非加密字段 出參解密成功
SELECT 原生SQL 加密字段 入?yún)⒓用艹晒?/font>
SELECT QueryWrapper 加密字段 入?yún)⒓用苁?/font>
UPDATE 原生SQL 加密字段 入?yún)⒓用艹晒?/font>
UPDATE UpdateWrapper 加密字段 入?yún)⒓用苁?/font>
UPDATE LambdaUpdateWrapper 加密字段 入?yún)⒓用艹晒?/font>
UPDATE updateById 加密字段 入?yún)⒓用艹晒?/font>
INSERT Service 加密字段 入?yún)⒓用艹晒?/font>

說明:

  • 官方的解答是 QueryWrapper、UpdateWrapper 底層是通過 @Param 來實現(xiàn)的,目前沒有做到入?yún)⒅С?typeHandler,如果做的話會影響性能。
  • LambdaUpdateWrapper 要求 MyBatis-Plus 版本為 3.5.3,PageHelper 也需要升級為 5.1.11,但是升級之后 PageHelper 分頁不好使了,待優(yōu)化。(升級后依賴參考 補充:2.3)

6.MyBatis Plus 缺陷

  • QueryWrapper 不支持入?yún)⒓用埽?/font>

  • UpdateWrapper 不支持入?yún)⒓用埽?/font>

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

7.歷史數(shù)據(jù)加密處理程序

@Override
public void encryptUser() {
    // 加密 用戶信息
    int count = this.count();
    int pageSize = 1000;
    int pageCount = count / pageSize + 1;
    // 必須用唯一且非空字段進(jìn)行排序,否則 pageHelper 查出來的數(shù)據(jù)可能會有重復(fù)。
    QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().orderByAsc("id");
    for (int i = 0; i < pageCount; i++) {
        log.info(">>>>>>>>>> 【INFO】加密用戶信息,當(dāng)前頁數(shù):{},總頁數(shù):{}", i + 1, pageCount);
        PageHelper.startPage(i + 1, pageSize);
        List<UserInfo> users = this.list(queryWrapper);
        new PageInfo<>(users);
        users.parallelStream().forEach(o -> {
            // 解密重復(fù)加密手機號
            while (AESUtil.defaultDecrypt(o.getPhoneNumber()) != null) {
                o.setPhoneNumber(AESUtil.defaultDecrypt(o.getPhoneNumber()));
            }
            // 解密重復(fù)加密身份證號
            while (AESUtil.defaultDecrypt(o.getIdCard()) != null) {
                o.setIdCard(AESUtil.defaultDecrypt(o.getIdCard()));
            }
        });
        this.updateBatchById(users);
    }
}

一般手機號AES加密后長度為32,我們可以根據(jù)這點通過SQL檢查加密情況:

select '未加密數(shù)量' state, COUNT(*) from t_user_info where length(phone_number) < 32 
union all
select '重復(fù)加密數(shù)量' state, COUNT(*)  from t_user_info where length(phone_number) > 32;

補充:測試實例

1 查詢測試

1.1 查詢信息,SQL實現(xiàn)
@Test
public void getUserInfoTest1() {
    UserInfo userInfo = userInfoService.findByAccount("testAccount");
    System.out.println("userInfo:" + userInfo);
    System.out.println("phone:" + userInfo.getPhone());
}

測試結(jié)果:出參解密成功

1.2 查詢信息,QueryWrapper實現(xiàn)
@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());
}

測試結(jié)果:出參解密成功

1.3 查詢信息,根據(jù)加密字段查詢,SQL實現(xiàn)
@Test
public void getUserInfoTest3() {
    UserInfo user = userInfoService.findByPhone("13888888888");
    System.out.println("userInfo:" + user);
    System.out.println("phone:" + user.getPhone());
}

(注意:入?yún)⑿枰褂胑l表達(dá)式指定 typeHandler)

測試結(jié)果:入?yún)⒓用艹晒?/font>

1.4 查詢信息,根據(jù)加密字段查詢,QueryWrapper實現(xiàn)
@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());
}

測試結(jié)果:入?yún)⒓用苁?,QueryWrapper底層使用 @Param 實現(xiàn),無法像 SQL 實現(xiàn)一樣指定 typeHandler。

2.測試更新

2.1 更新信息,SQL實現(xiàn)
@Test
public void updateUserInfoTest1() {
    userInfoService.updatePhoneByAccount("testAccount", "13888888888");
}

測試結(jié)果:入?yún)⒓用艹晒?/font>

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

測試結(jié)果:入?yún)⒓用苁?,UpdateWrapper底層使用 @Param 實現(xiàn),無法像 SQL 實現(xiàn)一樣指定 typeHandler。

2.3 更新信息,LambdaUpdateWrapper實現(xiàn)
@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();
}

測試結(jié)果:入?yún)⒓用艹晒Γ?.5.3支持,但是升級之后 PageHelper 分頁不好使了,待優(yōu)化)

升級后依賴:

<!-- 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實現(xiàn)
@Test
public void updateUserInfoTest4() {
    UserInfo userInfo = userInfoService.findByAccount("testAccount");
    userInfo.setPhone("13888888888");
    userInfoService.updateById(userInfo);
}

測試結(jié)果:入?yún)⒓用艹晒?/font>

3.測試插入

7.3.1 插入信息,SQL實現(xiàn)
@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());
}

測試結(jié)果:入?yún)⒓用艹晒?/font>

3.2 插入信息,Service實現(xiàn)
@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());
}

測試結(jié)果:入?yún)⒓用艹晒?/font>

整理完畢,完結(jié)撒花~





參考地址:

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文章來源地址http://www.zghlxwxcb.cn/news/detail-465831.html

到了這里,關(guān)于MyBatis Plus 數(shù)據(jù)庫字段加密處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • springboot mybatis-plus數(shù)據(jù)庫超時配置

    超時異常 寫XML 寫法,單位秒 Mapper類寫法,單位秒 超時異常 整個事務(wù)的超時時間,單位是秒。 它的原理大致是事務(wù)啟動時,事務(wù)上下文會計算一個到期時間deadLine(當(dāng)前時間+超時時間),當(dāng)mybatis - prepareStatement時,會調(diào)用 SpringManagedTransaction 的getTimeOut,該方法會計算事務(wù)剩

    2024年02月03日
    瀏覽(21)
  • Sql Server數(shù)據(jù)庫實現(xiàn)表中字段的列加密研究

    Sql Server數(shù)據(jù)庫實現(xiàn)表中字段的列加密研究

    ? ? ? ? 去年6月份的時候做過一個系統(tǒng),要對里面的一些敏感字段進(jìn)行一下加密。Sqlserver列加密可以參考官方文檔:SQL Server 技術(shù)文檔 - SQL Server | Microsoft Learn。主要看下來有三種加密方法:1、利用證書對數(shù)據(jù)進(jìn)行加密和解密。2、利用非對稱密鑰對數(shù)據(jù)進(jìn)行加密和解密。3、利

    2024年02月05日
    瀏覽(37)
  • Spring Boot + MyBatis-Plus實現(xiàn)數(shù)據(jù)庫讀寫分離

    Spring Boot + MyBatis-Plus實現(xiàn)數(shù)據(jù)庫讀寫分離

    ??Spring Boot + MyBatis-Plus實現(xiàn)數(shù)據(jù)庫讀寫分離 ☆* o(≧▽≦)o *☆嗨~我是IT·陳寒?? ?博客主頁:IT·陳寒的博客 ??該系列文章專欄:架構(gòu)設(shè)計 ??其他專欄:Java學(xué)習(xí)路線 Java面試技巧 Java實戰(zhàn)項目 AIGC人工智能 數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí) ??文章作者技術(shù)和水平有限,如果文中出現(xiàn)錯誤,希望

    2024年02月05日
    瀏覽(44)
  • 問題解決:使用Mybatis Plus的Mapper插入達(dá)夢數(shù)據(jù)庫報“數(shù)據(jù)溢出”錯誤

    問題解決:使用Mybatis Plus的Mapper插入達(dá)夢數(shù)據(jù)庫報“數(shù)據(jù)溢出”錯誤

    使用Mybatis Plus的Mapper插入達(dá)夢數(shù)據(jù)庫報“數(shù)據(jù)溢出”錯誤 問題描述 在進(jìn)行批量插入中,拋出異常為數(shù)據(jù)溢出 插入方法:this.baseMapper.insertBatchSomeColumn() 拋出異常:數(shù)據(jù)溢出 對失敗的數(shù)據(jù)進(jìn)行循環(huán),嘗試使用單個插入的方法,同樣拋出異常為數(shù)據(jù)溢出 插入方法:this.baseMapper

    2024年02月07日
    瀏覽(284)
  • MyBatis-Plus 查詢PostgreSQL數(shù)據(jù)庫jsonb類型保持原格式

    MyBatis-Plus 查詢PostgreSQL數(shù)據(jù)庫jsonb類型保持原格式

    在這篇文章,我們保存了數(shù)據(jù)庫的jsonb類型:MyBatis-Plus 實現(xiàn)PostgreSQL數(shù)據(jù)庫jsonb類型的保存與查詢 這篇文章介紹了模糊查詢json/jsonb類型:PostgreSQL 查詢json/jsonb是否存在某個片段 在模糊查詢json/jsonb之前,我們得拿到正確的json/jsonb片段,比如我們模糊查詢好幾個連著的鍵值對,

    2024年02月15日
    瀏覽(110)
  • 【Java】Mybatis查詢數(shù)據(jù)庫返回JSON格式的字段映射到實體類屬性

    今天遇到了一個bug,大概就是數(shù)據(jù)庫(Mysql)中有一個 type 類型字段,數(shù)據(jù)類型為json,大概是這樣的:[“蘋果”,“香蕉”,“葡萄”]的數(shù)據(jù)格式,這個bug的問題所在呢就是查詢后這個json格式的數(shù)據(jù)無法映射到我們實體類的屬性上,解決方案如下: 實體類的配置: @TableField

    2024年02月15日
    瀏覽(22)
  • Mybatis-Plus處理Mysql Json類型字段

    Mybatis-Plus處理Mysql Json類型字段

    Mysql 5.7.8開始支持Json對象和Json數(shù)組,但在Mysql 8版本中使用Json性能更佳。 使用Json格式的好處: 無須預(yù)定義字段:字段可以無限拓展,避免了ALTER ADD COLUMN的操作,使用更加靈活。 處理稀疏字段:避免了稀疏字段的NULL值,避免冗余存儲。 支持索引:相比于字符串格式的JSON,

    2024年02月03日
    瀏覽(28)
  • 【數(shù)據(jù)庫】Sql Server數(shù)據(jù)遷移,處理自增字段賦值

    【數(shù)據(jù)庫】Sql Server數(shù)據(jù)遷移,處理自增字段賦值

    給自己一個目標(biāo),然后堅持一段時間,總會有收獲和感悟! 在實際項目開發(fā)中,如果遇到高版本導(dǎo)入到低版本,或者低版本轉(zhuǎn)高版本,那么就會出現(xiàn)版本不兼容無法導(dǎo)入,此時通過程序遍歷創(chuàng)建表和添加數(shù)據(jù)方式可以解決 在 SQL Server 中,數(shù)據(jù)遷移是常見的場景之一。 以下是

    2024年02月08日
    瀏覽(29)
  • spring boot shardingsphere mybatis-plus druid mysql 搭建mysql數(shù)據(jù)庫讀寫分離架構(gòu)

    spring boot shardingsphere mybatis-plus druid mysql 搭建mysql數(shù)據(jù)庫讀寫分離架構(gòu)

    ##關(guān)于window mysql主從搭建簡單教程 傳送門?window mysql5.7 搭建主從同步環(huán)境-CSDN博客 ##父pom.xml ##模塊pom.xml ##yml配置 ##mapper.xml ##TestMapper ##TestService ##TestController ##瀏覽器訪問 ##數(shù)據(jù)庫

    2024年01月21日
    瀏覽(26)
  • Spring Boot使用jasypt處理數(shù)據(jù)庫賬號密碼等數(shù)據(jù)加密問題

    在我們業(yè)務(wù)場景中,項目中的application.yml 配置文件比如數(shù)據(jù)庫賬號密碼,的各種鏈接的username,password的值都是明文的,存在一定的安全隱患,可以使用jasypt?加密框架的方式進(jìn)行明文加密,進(jìn)而使得我們項目更加安全 注意這里排除了mybatis-plus的包可能是項目中有沖突依賴,

    2024年02月06日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包