├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── mybatis-mate-audit ├── build.gradle ├── pom.xml └── src │ ├── main │ ├── java │ │ └── mybatis │ │ │ └── mate │ │ │ └── audit │ │ │ ├── DataAuditApplication.java │ │ │ ├── entity │ │ │ └── User.java │ │ │ ├── mapper │ │ │ └── UserMapper.java │ │ │ └── service │ │ │ └── UserService.java │ └── resources │ │ ├── application.yml │ │ └── db │ │ ├── data-h2.sql │ │ └── schema-h2.sql │ └── test │ └── java │ └── mybatis │ └── mate │ └── audit │ └── DataAuditTest.java ├── mybatis-mate-datascope ├── build.gradle ├── pom.xml └── src │ ├── main │ ├── java │ │ └── mybatis │ │ │ └── mate │ │ │ └── datascope │ │ │ ├── DataScopeApplication.java │ │ │ ├── config │ │ │ ├── DataScopeConfig.java │ │ │ ├── MyGrantSupplier.java │ │ │ └── MybatisPlusConfig.java │ │ │ ├── entity │ │ │ ├── Department.java │ │ │ └── User.java │ │ │ ├── mapper │ │ │ └── UserMapper.java │ │ │ └── service │ │ │ └── UserService.java │ └── resources │ │ ├── application.yml │ │ ├── db │ │ ├── data-h2.sql │ │ └── schema-h2.sql │ │ └── mapper │ │ └── UserMapper.xml │ └── test │ └── java │ └── mybatis │ └── mate │ └── datascope │ └── DataScopeTest.java ├── mybatis-mate-ddl-mysql ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── ddl │ │ └── mysql │ │ ├── DdlMysqlApplication.java │ │ └── MysqlDdl.java │ └── resources │ ├── application.yml │ └── db │ ├── tag-data.sql │ ├── tag-schema.sql │ └── test_procedure.sql ├── mybatis-mate-ddl-oracle ├── build.gradle ├── libs │ └── ojdbc-11.2.0.3-jdk16.jar └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── ddl │ │ └── mysql │ │ ├── DdlOracleApplication.java │ │ └── OracleDdl.java │ └── resources │ ├── application.yml │ └── db │ ├── tag-data.sql │ └── tag-schema.sql ├── mybatis-mate-ddl-postgres ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── ddl │ │ └── postgres │ │ ├── DdlPostgresApplication.java │ │ └── PostgresDdl.java │ └── resources │ ├── application.yml │ └── db │ ├── tag-data.sql │ └── tag-schema.sql ├── mybatis-mate-dict ├── build.gradle ├── pom.xml └── src │ ├── main │ ├── java │ │ └── mybatis │ │ │ └── mate │ │ │ └── dict │ │ │ ├── DictApplication.java │ │ │ ├── config │ │ │ ├── BindType.java │ │ │ ├── DataBind.java │ │ │ └── JsonBindStrategy.java │ │ │ ├── entity │ │ │ ├── StatusEnum.java │ │ │ └── User.java │ │ │ └── mapper │ │ │ └── UserMapper.java │ └── resources │ │ ├── application.yml │ │ └── db │ │ ├── data-h2.sql │ │ └── schema-h2.sql │ └── test │ └── java │ └── mybatis │ └── mate │ └── dict │ └── DictTest.java ├── mybatis-mate-encrypt-mysql-aes ├── attr.sql ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── sm │ │ └── mysql │ │ └── aes │ │ ├── EncryptMysqlAesApplication.java │ │ ├── controller │ │ └── TestController.java │ │ ├── entity │ │ ├── AttrVO.java │ │ └── ComAttr.java │ │ └── mapper │ │ └── ComAttrMapper.java │ └── resources │ └── application.yml ├── mybatis-mate-encrypt-sm2-sm3-sm4 ├── build.gradle ├── pom.xml └── src │ ├── main │ ├── java │ │ └── mybatis │ │ │ └── mate │ │ │ └── sm │ │ │ ├── EncryptApplication.java │ │ │ ├── config │ │ │ └── DataBind.java │ │ │ ├── entity │ │ │ └── User.java │ │ │ └── mapper │ │ │ └── UserMapper.java │ └── resources │ │ ├── application.yml │ │ ├── db │ │ └── schema-h2.sql │ │ ├── sm4.js │ │ └── sm4_test.html │ └── test │ └── java │ └── mybatis │ └── mate │ └── sm │ └── EncryptTest.java ├── mybatis-mate-encrypt ├── build.gradle ├── pom.xml └── src │ ├── main │ ├── java │ │ └── mybatis │ │ │ └── mate │ │ │ └── encrypt │ │ │ ├── EncryptApplication.java │ │ │ ├── config │ │ │ ├── CustomEncryptor.java │ │ │ ├── MyEncryptor.java │ │ │ ├── SpiceBaseMapper.java │ │ │ ├── SpiceSqlInjector.java │ │ │ └── TenantEncryptor.java │ │ │ ├── entity │ │ │ ├── User.java │ │ │ ├── UserInfo.java │ │ │ ├── dto │ │ │ │ └── UserDTO.java │ │ │ ├── type │ │ │ │ └── RSATypeHandler.java │ │ │ └── vo │ │ │ │ └── UserVO.java │ │ │ └── mapper │ │ │ └── UserMapper.java │ └── resources │ │ ├── application.yml │ │ ├── db │ │ ├── data-h2.sql │ │ └── schema-h2.sql │ │ └── mapper │ │ └── UserMapper.xml │ └── test │ └── java │ └── mybatis │ └── mate │ └── encrypt │ └── EncryptTest.java ├── mybatis-mate-hot-reload └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── hotreload │ │ ├── WatchServiceTest.java │ │ ├── entity │ │ └── User.java │ │ └── mapper │ │ └── UserMapper.java │ └── resources │ ├── m │ └── Mm.xml │ └── mapper │ └── UserMapper.xml ├── mybatis-mate-jsonbind ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── dict │ │ ├── JsonBindApplication.java │ │ ├── config │ │ └── JsonBindStrategy.java │ │ ├── controller │ │ └── UserController.java │ │ ├── entity │ │ ├── StatusEnum.java │ │ └── User.java │ │ └── mapper │ │ └── UserMapper.java │ └── resources │ ├── application.yml │ └── db │ ├── data-h2.sql │ └── schema-h2.sql ├── mybatis-mate-sensitive-jackson ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── sensitive │ │ └── jackson │ │ ├── SensitiveJacksonApplication.java │ │ ├── config │ │ ├── MyResponseBodyAdvice.java │ │ └── SensitiveStrategyConfig.java │ │ ├── controller │ │ └── UserController.java │ │ ├── entity │ │ └── User.java │ │ └── mapper │ │ └── UserMapper.java │ └── resources │ ├── application.yml │ └── db │ ├── data-h2.sql │ └── schema-h2.sql ├── mybatis-mate-sensitive-words ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── sensitivewords │ │ ├── SensitiveWordsApplication.java │ │ ├── config │ │ ├── ParamsConfig.java │ │ ├── SensitiveRequestBodyAdvice.java │ │ └── Sensitived.java │ │ ├── controller │ │ └── ArticleController.java │ │ ├── entity │ │ ├── Article.java │ │ ├── ArticleNoneSensitive.java │ │ └── SensitiveWords.java │ │ └── mapper │ │ └── SensitiveWordsMapper.java │ └── resources │ ├── TestJson.http │ ├── application.yml │ └── db │ ├── data-h2.sql │ └── schema-h2.sql ├── mybatis-mate-sharding-dynamic ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── sharding │ │ └── dynamic │ │ ├── ShardingDynamicApplication.java │ │ ├── config │ │ ├── MyDatabaseIdProvider.java │ │ ├── MyShardingProcessor.java │ │ └── ShardingConfig.java │ │ ├── controller │ │ └── UserController.java │ │ ├── entity │ │ └── User.java │ │ └── mapper │ │ └── UserMapper.java │ └── resources │ ├── application.yml │ └── mapper │ └── UserMapper.xml ├── mybatis-mate-sharding-jta-atomikos ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── sharding │ │ └── jta │ │ └── atomikos │ │ ├── ShardingJtaAtomikosApplication.java │ │ ├── config │ │ ├── Db1.java │ │ ├── Db2.java │ │ ├── Db3.java │ │ ├── PerformanceInterceptor.java │ │ └── ShardingConfig.java │ │ ├── controller │ │ └── TestController.java │ │ ├── entity │ │ ├── Log.java │ │ ├── Order.java │ │ └── Sku.java │ │ ├── mapper │ │ ├── LogMapper.java │ │ ├── OrderMapper.java │ │ └── SkuMapper.java │ │ └── service │ │ ├── BuyService.java │ │ ├── LogService.java │ │ ├── OrderService.java │ │ └── SkuService.java │ └── resources │ ├── application.yml │ └── db │ ├── log-db3.sql │ ├── order-db1.sql │ └── sku-db2.sql ├── mybatis-mate-sharding ├── build.gradle ├── pom.xml └── src │ └── main │ ├── java │ └── mybatis │ │ └── mate │ │ └── sharding │ │ ├── ShardingApplication.java │ │ ├── config │ │ ├── DdlConfig.java │ │ ├── MyShardingProcessor.java │ │ ├── MyShardingStrategy.java │ │ ├── MysqlDdl.java │ │ ├── PostgresDdl.java │ │ └── ScheduledConfig.java │ │ ├── controller │ │ └── UserController.java │ │ ├── entity │ │ └── User.java │ │ ├── mapper │ │ └── UserMapper.java │ │ └── service │ │ └── UserService.java │ └── resources │ ├── application.yml │ └── db │ ├── user-mysql.sql │ └── user-postgres.sql ├── pom.xml ├── settings.gradle └── 国密SM2.3.4算法使用规范 ├── SM2密码算法使用规范.pdf ├── 国密算法SM2-1.pdf ├── 国密算法SM2-2.pdf ├── 国密算法SM3.pdf └── 国密算法SMS4.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore file 2 | *.iml 3 | *.log 4 | *.logs 5 | *.ipr 6 | *.classpath 7 | *.project 8 | /hs_err_pid*.log 9 | libs 10 | 11 | # ignore direcoties 12 | transaction-logs 13 | tmlog* 14 | /c:/ 15 | **/out/** 16 | /logs/ 17 | **/contiperf-report/ 18 | **/build/ 19 | **/target/ 20 | .gradle/ 21 | .idea/ 22 | .settings/ 23 | bin/ 24 | /hs_err*.log 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | > SpringBoot 2 使用 1..0-sp2 版本 3 | 4 | > SpringBoot 3 使用 1..0 版本 5 | 6 | 7 | ### 版本 1.3.6 发布日期 2024-05-28 8 | 9 | - 升级依赖支持最新 jsqParser 4.9+ 10 | - 升级支持 MybatisPlus 3.5.6 11 | 12 | 13 | ### 版本 1.3.5 发布日期 2024-04-19 14 | 15 | - 支持加密异常控制 16 | 17 | 18 | ### 版本 1.3.4 发布日期 2024-02-28 19 | 20 | - 解决多数据源 bug 21 | - 优化代码 22 | 23 | ### 版本 1.3.2 发布日期 2023-08-25 24 | 25 | - 优化脱敏变量声明逻辑 26 | - 支持执行加密解密租户可控逻辑 27 | - 其它优化 28 | 29 | 30 | ### 版本 1.3.1 发布日期 2023-08-10 31 | 32 | - 优化 DDL 支持存储过程自定义命令行分隔符 33 | - 优化判断空值不加密 34 | 35 | 36 | ### 版本 1.3.0 发布日期 2023-08-01 37 | 38 | - 多数据源数据检测心跳测试SQL获取优化 39 | - 多数据源健康检查优化 40 | - 默认主数据与获取方式优化 41 | - 数据权限拦截忽略 BUG 修复 42 | - 其它优化 43 | 44 | ### 版本 1.2.9 发布日期 2023-03-01 45 | 46 | - 修复脱敏多个字段忽略脱敏情况bug修复 47 | - 支持指定属性不脱敏控制 48 | 49 | 50 | ### 版本 1.2.8 发布日期 2023-01-05 51 | 52 | - 支持 spring boot 3.0 + 问题bug修复 53 | 54 | 55 | ### 版本 1.2.7 发布日期 2022-12-14 56 | 57 | - 支持 spring boot 3.0 + 58 | - 优化 DDL 修复连接相关 BUG 59 | - 优化脱敏自动清空脱敏标记 60 | - 其它部分优化 61 | 62 | ### 版本 1.2.6 发布日期 2022-08-30 63 | 64 | - 新增多数据源处理器可控制清理缓存DatabaseKey 65 | - 优化 Pg-DDL 代码执行逻辑 66 | 67 | ### 版本 1.2.5 发布日期 2022-07-11 68 | 69 | - 数据库主从切换修改为默认主无效找从库 70 | - 新增数据库主动检查配置示例 71 | - 升级依赖及其它 72 | 73 | ### 版本 1.2.4 发布日期 2022-04-18 74 | 75 | - 解决处理器判断逻辑异常 Bug 76 | 77 | ### 版本 1.2.3 发布日期 2022-03-15 78 | 79 | - 重构 DDL 部分逻辑,支持 Oracle 数据库 80 | 81 | ### 版本 1.2.2 发布日期 2022-03-10 82 | 83 | - 多数据源yml配置时候数据库连接释放bug修复 84 | 85 | ### 版本 1.2.1 发布日期 2022-03-01 86 | 87 | - 动态数据源首次切换类方法bug修复 88 | 89 | ### 版本 1.1.3 发布日期 2022-01-22 90 | 91 | - 修复类权限 bug 92 | - 支持二次授权 93 | 94 | ### 版本 1.1.2 发布日期 2022-01-15 95 | 96 | - 修改 1.1.1 bug 97 | - 优化代码 98 | 99 | ### 版本 1.1.1 发布日期 2022-01-12 100 | 101 | - 支持返回 json 数据动态绑定虚拟属性 102 | - 手动调用审计对比方法 DataAuditor.compare(obj1, obj2) 103 | 104 | ### 版本 1.1.0 发布日期 2021-12-12 105 | 106 | - 新增 sharding 默认处理器,支持可配置处理数据源切换逻辑 107 | - 升级相关编译基础依赖包 modelmapper javers 108 | - 优化核心处理代码,调整授权证书支持过期 109 | 110 | ### 版本 1.0.18 发布日期 2021-11-16 111 | 112 | - 解决 1.0.17 存在的 bug 113 | 114 | ### 版本 1.0.17 发布日期 2021-11-15 115 | 116 | - 该版本有 bug 不推荐使用 117 | - 兼容支持 spring boot 2.0 及以下版本 118 | 119 | ### 版本 1.0.16 发布日期 2021-10-23 120 | 121 | - DdlScript 新增事务配置参数 122 | - 调整加解密错误日志打印 123 | - 数据范围别名新增非空判断 124 | - 新增动态数据源处理器及示例 125 | 126 | ### 版本 1.0.15 发布日期 2021-10-02 127 | 128 | - 修复数据范围权限同 mapper 注解处理 bug 129 | - 优化多数据源注解执行流程 130 | 131 | ### 版本 1.0.14 发布日期 2021-09-23 132 | 133 | - 优化 DDL 多数据源数据结构自动维护 134 | - 优化多数据源新增 jta 事务 135 | 136 | ### 版本 1.0.13 发布日期 2021-09-10 137 | 138 | - 新增数据敏感词过滤处理器 139 | - 采用 AC 匹配敏感词算法 140 | 141 | ### 版本 1.0.12 发布日期 2021-09-08 142 | 143 | - 支持跳过数据脱密显示原始内容(用于编辑) 144 | - 支持 Base64 算法 RSA 算法 145 | - 支持 SM2 SM3 SM4 国密算法 146 | - 补充测试用例 147 | 148 | ### 版本 1.0.11 发布日期 2021-09-06 149 | 150 | - 解决数据绑定混淆加密同时注解异常问题 151 | - 解决结果集返回 null 无法解密问题 152 | 153 | ### 版本 1.0.10 发布日期 2021-09-03 154 | 155 | - 优化数据绑定调整为自主可控任意对象属性绑定 156 | - 新增SM4国密算法 157 | 158 | ### 版本 1.0.9 发布日期 2021-09-01 159 | 160 | - 密码新增 AES 内置算法 161 | - 支持任意查询结果加密解密逻辑 162 | - 支持父类加密属性可用及子类重写加密逻辑 163 | 164 | ### 版本 1.0.8 发布日期 2021-08-31 165 | 166 | - 优化字段加密功能支持注解可配置处理器 167 | - 加解密对象对外提供可访问可操作暴露 168 | - 双向加密可控支持 169 | 170 | ### 版本 1.0.7 发布日期 2021-08-28 171 | 172 | - 调整 ddl 读取本地包我sql文件读取方式修改为 spring 核心包 ClassPathResource 类处理 173 | - 加密支持 md5 加密 32 位 16 位 不可逆算法 174 | - 优化数据权限处理流程 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mybatis-mate 2 | 3 | #### 介绍 4 | mybatis-plus 企业(数据优雅处理)模块 5 | 6 | > 营造良好的软件生态,合规渠道获得软件作者授权。 7 | 8 | - Spring Boot 引入自动依赖注解包(该包自动会引入 annotation 注解包) 9 | 10 | > SpringBoot 3.X 使用 1.3.6 版本 SpringBoot 2.X 使用 1.3.6-sp2 版本 11 | 12 | [点击查看当前最新版本](https://central.sonatype.com/artifact/com.baomidou/mybatis-mate-starter) 13 | 14 | - 注意不同密钥需要使用指定算法生成密钥,例如 `SM2` `SM4` 使用 `KeyGenerator` 类生成,不可随意编写任意字符串。 15 | 16 | ``` 17 | 18 | com.baomidou 19 | mybatis-mate-starter 20 | 1.3.6 21 | 22 | ``` 23 | 24 | - 注解(实体分包使用) 25 | 26 | ``` 27 | 28 | com.baomidou 29 | mybatis-mate-annotation 30 | 1.3.6 31 | 32 | ``` 33 | 34 | - 咨询作者 35 | 36 | ![微信 wx153666](https://images.gitee.com/uploads/images/2021/0903/235825_2d017339_12260.jpeg) 37 | 38 | - mybatis-mate-data-audit :数据审计(对账)示例 39 | 40 | - mybatis-mate-data-datascope :数据范围(数据权限)示例 `包含二次授权逻辑` 41 | 42 | - mybatis-mate-ddl-mysql :表结构自动维护 Mysql 示例 43 | 44 | - mybatis-mate-ddl-postgres :表结构自动维护 PostgreSQL 示例 45 | 46 | - mybatis-mate-dict :字段数据字典自动映射示例 47 | 48 | `该功能可以绑定任意类型的数据源,例如:根据 orderId 绑定 orderNo` 49 | 50 | - mybatis-mate-encrypt :字段加密解密示例 51 | 52 | - mybatis-mate-encrypt-mysql-aes :数据库 mysql 字段 aes 双向加密解密示例 53 | 54 | - mybatis-mate-encrypt-sm2-sm3-sm4 :国密 sm2 sm3 sm4 加密算法示例 55 | 56 | - mybatis-mate-jsonbind :返回 json 数据动态绑定虚拟属性 示例 57 | 58 | - mybatis-mate-sensitive-jackson :字段脱敏 jackson 实现示例 59 | 60 | - mybatis-mate-sensitive-words :请求参数 敏感词 过滤 AC 算法 示例 61 | 62 | - mybatis-mate-sharding :多数据源分库分表(读写分离)健康检查自动切换示例 63 | 64 | - mybatis-mate-sharding-dynamic :多数据源动态加载卸载示例(代码初始化数据源) 65 | 66 | - mybatis-mate-sharding-jta-atomikos :多数据源事务( jta atomikos)示例 67 | 68 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // 编译脚本 2 | buildscript { 3 | ext { 4 | springBootVersion = "3.3.0" 5 | mybatisPlusVersion = "3.5.6" 6 | } 7 | 8 | // 仓库配置 9 | repositories { 10 | mavenLocal() 11 | maven { url 'https://maven.aliyun.com/repository/central' } 12 | maven { url 'https://maven.aliyun.com/repository/spring' } 13 | maven { url 'https://maven.aliyun.com/repository/google' } 14 | maven { url 'https://repo.spring.io/release' } 15 | maven { url 'https://repo.spring.io/milestone' } 16 | } 17 | 18 | dependencies { 19 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 20 | } 21 | } 22 | 23 | description = "MybatisPlus 企业模块版" 24 | 25 | // 项目配置 26 | allprojects { 27 | group "mybatis.mate" 28 | version "1.0" 29 | 30 | } 31 | 32 | // 子模块配置 33 | subprojects { 34 | apply plugin: 'java-library' 35 | apply plugin: 'maven-publish' 36 | apply plugin: "io.spring.dependency-management" 37 | apply plugin: 'org.springframework.boot' 38 | 39 | tasks.withType(JavaCompile) { 40 | options.encoding = 'UTF-8' 41 | options.warnings = false 42 | } 43 | 44 | // 仓库配置 45 | repositories { 46 | mavenLocal() 47 | maven { url 'https://maven.aliyun.com/repository/central' } 48 | maven { url 'https://maven.aliyun.com/repository/spring' } 49 | maven { url 'https://maven.aliyun.com/repository/google' } 50 | maven { url 'https://repo.spring.io/release' } 51 | maven { url 'https://repo.spring.io/milestone' } 52 | mavenCentral() 53 | } 54 | 55 | // 依赖管理 56 | dependencyManagement { 57 | imports { 58 | mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}" 59 | } 60 | 61 | dependencies { 62 | dependency("com.baomidou:mybatis-plus-spring-boot3-starter:${mybatisPlusVersion}") 63 | dependency("com.baomidou:mybatis-plus-core:${mybatisPlusVersion}") 64 | dependency("com.baomidou:mybatis-plus-extension:${mybatisPlusVersion}") 65 | dependency("org.modelmapper:modelmapper:2.4.5") 66 | dependency("org.aspectj:aspectjweaver:1.9.7") 67 | dependency("org.jasypt:jasypt:1.9.3") 68 | dependency("org.javers:javers-core:6.5.3") 69 | dependency("com.h2database:h2:1.4.200") 70 | dependency("org.postgresql:postgresql:42.3.1") 71 | dependency("mysql:mysql-connector-java:8.0.26") 72 | // 编译测试 73 | dependency("junit:junit:4.12") 74 | } 75 | } 76 | 77 | // 依赖配置 78 | dependencies { 79 | // 日志 80 | api("org.slf4j:slf4j-api") 81 | 82 | // api fileTree(dir: "../libs", include: "*.jar") 83 | 84 | // spring boot 2.X 请用 1.3.2-sp2 版本 85 | api("com.baomidou:mybatis-mate-starter:1.3.6") 86 | 87 | api("com.baomidou:mybatis-plus-spring-boot3-starter") 88 | api("org.springframework.boot:spring-boot-starter-web") 89 | api("org.springframework.boot:spring-boot-starter-jdbc") 90 | 91 | // lombok 92 | compileOnly("org.projectlombok:lombok") 93 | annotationProcessor("org.projectlombok:lombok") 94 | testAnnotationProcessor("org.projectlombok:lombok") 95 | testCompileOnly("org.projectlombok:lombok") 96 | } 97 | 98 | // 编译环境 JDK1.8 99 | sourceCompatibility = JavaVersion.VERSION_17 100 | targetCompatibility = JavaVersion.VERSION_17 101 | } 102 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baomidou/mybatis-mate-examples/49536203f7240b13a95e5dbf5a6e82314bad515e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.6-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /mybatis-mate-audit/build.gradle: -------------------------------------------------------------------------------- 1 | description "数据审计示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | implementation("org.javers:javers-core") 6 | 7 | testImplementation("org.springframework.boot:spring-boot-starter-test") 8 | testImplementation("junit:junit") 9 | } 10 | -------------------------------------------------------------------------------- /mybatis-mate-audit/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-audit 11 | 12 | 13 | 14 | org.javers 15 | javers-core 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-maven-plugin 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /mybatis-mate-audit/src/main/java/mybatis/mate/audit/DataAuditApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.audit; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | @EnableAsync 8 | @SpringBootApplication 9 | public class DataAuditApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(DataAuditApplication.class, args); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /mybatis-mate-audit/src/main/java/mybatis/mate/audit/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.audit.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | import org.javers.core.metamodel.annotation.PropertyName; 7 | 8 | import java.math.BigDecimal; 9 | 10 | @Getter 11 | @Setter 12 | @ToString 13 | public class User { 14 | private Long id; 15 | private String username; 16 | // 该注解可以指定数据审计输出内容 17 | @PropertyName("手机号码") 18 | private String mobile; 19 | private String email; 20 | private BigDecimal wallet; 21 | private BigDecimal amount; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /mybatis-mate-audit/src/main/java/mybatis/mate/audit/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.audit.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.audit.entity.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface UserMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-audit/src/main/java/mybatis/mate/audit/service/UserService.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.audit.service; 2 | 3 | import lombok.AllArgsConstructor; 4 | import mybatis.mate.audit.DataAuditEvent; 5 | import mybatis.mate.audit.DataAuditor; 6 | import mybatis.mate.audit.entity.User; 7 | import mybatis.mate.audit.mapper.UserMapper; 8 | import org.javers.core.diff.Change; 9 | import org.javers.core.diff.changetype.ValueChange; 10 | import org.springframework.context.ApplicationEventPublisher; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | @Service 15 | @AllArgsConstructor 16 | public class UserService { 17 | private UserMapper userMapper; 18 | private ApplicationEventPublisher applicationEventPublisher; 19 | 20 | @Transactional(rollbackFor = Exception.class) 21 | public void dataAudit() { 22 | // 执行数据库操作 23 | User user = userMapper.selectById(1L); 24 | System.err.println(user); 25 | System.err.println("手动调用审计对比方法"); 26 | DataAuditor.compare(user, userMapper.selectById(3L)).forEach(change -> printChange(change)); 27 | 28 | System.err.println("-----publishEvent-----begin"); 29 | // 发送事务监听的事件,异步回调 30 | applicationEventPublisher.publishEvent(new DataAuditEvent((t) -> { 31 | System.err.println("-----触发异步回调-----"); 32 | User user2 = userMapper.selectById(2L); 33 | System.err.println(user2); 34 | t.apply(user, user2).forEach(change -> printChange(change)); 35 | })); 36 | System.err.println("-----publishEvent-----end"); 37 | } 38 | 39 | private void printChange(Change change) { 40 | ValueChange vc = (ValueChange) change; 41 | System.err.println(String.format("%s不匹配,期望值 %s 实际值 %s", vc.getPropertyName(), 42 | vc.getLeft(), vc.getRight())); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mybatis-mate-audit/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | data-locations: classpath:db/data-h2.sql 12 | mode: always 13 | 14 | # Mybatis Mate 配置 15 | mybatis-mate: 16 | cert: 17 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 18 | grant: thisIsTestLicense 19 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 20 | # 开启数据审计 21 | audit: true 22 | 23 | # Logger Config 24 | logging: 25 | level: 26 | mybatis.mate: error 27 | -------------------------------------------------------------------------------- /mybatis-mate-audit/src/main/resources/db/data-h2.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM user; 2 | 3 | INSERT INTO user (id, username, mobile, email, wallet, amount) VALUES 4 | (1, 'Jack', '15315388888', 'test@baomidou.com', 11850, 100), 5 | (2, 'Jack', '15315366666', 'test@baomidou.com', 11850.00, 100.06), 6 | (3, 'Jack', '15315366123', 'test@baomidou.com', 1135, 100); 7 | -------------------------------------------------------------------------------- /mybatis-mate-audit/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | 3 | CREATE TABLE user 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 7 | mobile VARCHAR(11) NULL DEFAULT NULL COMMENT '手机号', 8 | email VARCHAR(255) NULL DEFAULT NULL COMMENT '邮箱', 9 | wallet DECIMAL(20,2) NULL DEFAULT NULL COMMENT '钱包余额', 10 | amount DECIMAL(20,2) NULL DEFAULT NULL COMMENT '存蓄金额', 11 | PRIMARY KEY (id) 12 | ); -------------------------------------------------------------------------------- /mybatis-mate-audit/src/test/java/mybatis/mate/audit/DataAuditTest.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.audit; 2 | 3 | import mybatis.mate.audit.service.UserService; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | /** 11 | * 字段加解密测试 12 | */ 13 | @RunWith(SpringRunner.class) 14 | @SpringBootTest 15 | public class DataAuditTest { 16 | @Autowired 17 | private UserService userService; 18 | 19 | @Test 20 | public void test() { 21 | userService.dataAudit(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/build.gradle: -------------------------------------------------------------------------------- 1 | description "数据审计示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | implementation("com.github.jsqlparser:jsqlparser") 6 | 7 | testImplementation("org.springframework.boot:spring-boot-starter-test") 8 | testImplementation("junit:junit") 9 | } 10 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-datascope 11 | 12 | 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-maven-plugin 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/DataScopeApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | @EnableAsync 8 | @SpringBootApplication 9 | public class DataScopeApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(DataScopeApplication.class, args); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/config/DataScopeConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope.config; 2 | 3 | import mybatis.mate.databind.RequestDataTransfer; 4 | import mybatis.mate.datascope.AbstractDataScopeProvider; 5 | import mybatis.mate.datascope.DataColumnProperty; 6 | import mybatis.mate.datascope.DataScopeProperty; 7 | import mybatis.mate.datascope.IDataScopeProvider; 8 | import net.sf.jsqlparser.expression.Parenthesis; 9 | import net.sf.jsqlparser.expression.StringValue; 10 | import net.sf.jsqlparser.expression.operators.conditional.AndExpression; 11 | import net.sf.jsqlparser.expression.operators.relational.EqualsTo; 12 | import net.sf.jsqlparser.expression.operators.relational.ExpressionList; 13 | import net.sf.jsqlparser.expression.operators.relational.InExpression; 14 | import net.sf.jsqlparser.expression.operators.relational.LikeExpression; 15 | import net.sf.jsqlparser.schema.Column; 16 | import net.sf.jsqlparser.statement.delete.Delete; 17 | import net.sf.jsqlparser.statement.select.PlainSelect; 18 | import org.apache.ibatis.mapping.MappedStatement; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | @Configuration 26 | public class DataScopeConfig { 27 | public final static String TEST = "test"; 28 | public final static String TEST_CLASS = "testClass"; 29 | 30 | @Bean 31 | public IDataScopeProvider dataScopeProvider() { 32 | return new AbstractDataScopeProvider() { 33 | 34 | /** 35 | * 这里是 Select 查询 Where 条件 36 | */ 37 | @Override 38 | public void setWhere(PlainSelect plainSelect, Object[] args, DataScopeProperty dataScopeProperty) { 39 | // args 中包含 mapper 方法的请求参数,需要使用可以自行获取 40 | 41 | // 调用下面方法需要手动清空参数,方法 RequestDataTransfer.remove(); 42 | Map params = RequestDataTransfer.getAll(); 43 | if (null != params) { 44 | // String myParam = RequestDataTransfer.get("myParam"); 这样也可以取到,注意!该方法会自动清空参数 45 | System.err.println("这是一个动态参数:" + params.get("myParam")); 46 | } 47 | 48 | /* 49 | // 测试数据权限,最终执行 SQL 语句 50 | SELECT u.* FROM user u WHERE (u.department_id IN ('1', '2', '3', '5')) 51 | AND u.mobile LIKE '%1533%' 52 | */ 53 | if (TEST.equals(dataScopeProperty.getType())) { 54 | // 业务 test 类型 55 | List dataColumns = dataScopeProperty.getColumns(); 56 | for (DataColumnProperty dataColumn : dataColumns) { 57 | if ("department_id".equals(dataColumn.getName())) { 58 | // 追加部门字段 IN 条件,也可以是 SQL 语句 59 | ExpressionList itemsList = new ExpressionList( 60 | new StringValue("1"), 61 | new StringValue("2"), 62 | new StringValue("3"), 63 | new StringValue("5") 64 | ); 65 | InExpression inExpression = new InExpression(new Column(dataColumn.getAliasDotName()), itemsList); 66 | if (null == plainSelect.getWhere()) { 67 | // 不存在 where 条件 68 | plainSelect.setWhere(new Parenthesis(inExpression)); 69 | } else { 70 | // 存在 where 条件 and 处理 71 | plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), inExpression)); 72 | } 73 | } else if ("mobile".equals(dataColumn.getName())) { 74 | // 支持一个自定义条件 75 | LikeExpression likeExpression = new LikeExpression(); 76 | likeExpression.setLeftExpression(new Column(dataColumn.getAliasDotName())); 77 | likeExpression.setRightExpression(new StringValue("%1533%")); 78 | plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), likeExpression)); 79 | } 80 | } 81 | 82 | // SQL 解析写法 83 | // try { 84 | // Expression selectExpression = CCJSqlParserUtil.parseCondExpression("username='333'", true); 85 | // plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), selectExpression)); 86 | // } catch (Exception e) { 87 | // e.printStackTrace(); 88 | // } 89 | } 90 | 91 | else if (TEST_CLASS.equals(dataScopeProperty.getType())) { 92 | System.err.println("----------------使用类注解权限----------------"); 93 | } 94 | } 95 | 96 | @Override 97 | public void processInsert(Object[] args, MappedStatement mappedStatement, DataScopeProperty dataScopeProperty) { 98 | System.err.println("------------------ 执行【插入】你可以干点什么"); 99 | } 100 | 101 | @Override 102 | public void processDelete(Object[] args, MappedStatement mappedStatement, DataScopeProperty dataScopeProperty) { 103 | /** 104 | * 这是删除自定义处理逻辑,插入更新需要限制条件可以参考这里 105 | */ 106 | if (TEST_CLASS.equals(dataScopeProperty.getType())) { 107 | processStatements(args, mappedStatement, (statement, index) -> { 108 | Delete delete = (Delete) statement; 109 | List dataColumns = dataScopeProperty.getColumns(); 110 | for (DataColumnProperty dataColumn : dataColumns) { 111 | if ("department_id".equals(dataColumn.getName())) { 112 | EqualsTo equalsTo = new EqualsTo(); 113 | equalsTo.setLeftExpression(new Column(dataColumn.getAliasDotName())); 114 | equalsTo.setRightExpression(new StringValue("1")); 115 | delete.setWhere(new AndExpression(delete.getWhere(), equalsTo)); 116 | } 117 | } 118 | }); 119 | } 120 | } 121 | 122 | @Override 123 | public void processUpdate(Object[] args, MappedStatement mappedStatement, DataScopeProperty dataScopeProperty) { 124 | System.err.println("------------------ 执行【更新】 你可以干点什么"); 125 | } 126 | }; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/config/MyGrantSupplier.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope.config; 2 | 3 | import mybatis.mate.license.IGrantSupplier; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.nio.charset.StandardCharsets; 7 | import java.util.Base64; 8 | 9 | /** 10 | * 这是二次授权逻辑,加密原来 grant 混入自己的授权逻辑,比如可以验证 Mac 地址 11 | */ 12 | @Component 13 | public class MyGrantSupplier implements IGrantSupplier { 14 | 15 | @Override 16 | public String get(String grant) { 17 | /** 18 | * 获取到自定义加密逻辑字符串,然后验证 Mac 地址什么的认证客户机唯一性,案例配置的 grant 是下面代码加密的 19 | * 20 | *
21 |          * Base64.getEncoder().encodeToString("thisIsTestLicense#张三".getBytes(StandardCharsets.UTF_8));
22 |          * 
23 | */ 24 | String myGrant = new String(Base64.getDecoder().decode(grant.getBytes(StandardCharsets.UTF_8))); 25 | System.err.println("这是我的二次授权证书:" + myGrant); 26 | 27 | // 把混淆解密的原证书在内存中返回给顶层授权逻辑 28 | return myGrant.split("#")[0]; 29 | } 30 | 31 | public static void main(String[] args) { 32 | System.out.println(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope.config; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class MybatisPlusConfig { 10 | 11 | @Bean 12 | public PaginationInnerInterceptor paginationInnerInterceptor() { 13 | return new PaginationInnerInterceptor(DbType.H2); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/entity/Department.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | @Getter 8 | @Setter 9 | @ToString 10 | public class Department { 11 | private Long id; 12 | private Long pid; 13 | private String name; 14 | private Integer sort; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope.entity; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @ToString 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class User { 11 | private Long id; 12 | private Long departmentId; 13 | private String username; 14 | private String mobile; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.Wrapper; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.baomidou.mybatisplus.core.metadata.IPage; 6 | import com.baomidou.mybatisplus.core.toolkit.Constants; 7 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 8 | import mybatis.mate.annotation.DataColumn; 9 | import mybatis.mate.annotation.DataScope; 10 | import mybatis.mate.datascope.config.DataScopeConfig; 11 | import mybatis.mate.datascope.entity.User; 12 | import org.apache.ibatis.annotations.Mapper; 13 | import org.apache.ibatis.annotations.Param; 14 | import org.apache.ibatis.annotations.Select; 15 | 16 | import java.util.List; 17 | 18 | @DataScope(type = DataScopeConfig.TEST_CLASS, value = { 19 | // 这里 DataScope 作用于整个类,优先级小于方法 DataScope 注解 20 | @DataColumn(name = "department_id") 21 | }) 22 | @Mapper 23 | public interface UserMapper extends BaseMapper { 24 | 25 | // 测试 test 类型数据权限范围,混合分页模式 26 | @DataScope(type = DataScopeConfig.TEST, value = { 27 | // 关联表 user 别名 u 指定部门字段权限 28 | @DataColumn(alias = "u", name = "department_id"), 29 | // 关联表 user 别名 u 指定手机号字段(自己判断处理) 30 | @DataColumn(alias = "u", name = "mobile") 31 | }) 32 | @Select("select u.* from user u") 33 | List selectTestList(IPage page, Long id, @Param("name") String username); 34 | 35 | @DataScope(type = DataScopeConfig.TEST, value = { 36 | @DataColumn(alias = "u", name = "department_id"), 37 | @DataColumn(alias = "u", name = "mobile") 38 | }) 39 | @Select("select u.* from user u join department d on u.department_id = d.id") 40 | List selectTestJoin(IPage page, Long id, @Param("name") String username); 41 | 42 | @DataScope(type = DataScopeConfig.TEST, value = { 43 | @DataColumn(alias = "u", name = "department_id"), 44 | @DataColumn(alias = "u", name = "mobile") 45 | }) 46 | List selectDeptNamesByUserIds(@Param("userIds") List userIds, @Param("username") String username); 47 | 48 | /** 49 | * 忽略某个方法 50 | */ 51 | @DataScope(ignore = true) 52 | List selectTestIgnoreDataScope(@Param("userIds") List userIds, @Param("username") String username); 53 | 54 | /** 55 | * 使用类注解 56 | */ 57 | List selectTestXmlSql(@Param("userIds") List userIds, @Param("username") String username); 58 | 59 | default IPage page(IPage page, String mobile) { 60 | return selectPage(page, Wrappers.lambdaQuery().likeRight(User::getMobile, mobile)); 61 | } 62 | 63 | @DataScope(type = "def") 64 | @Override 65 | List selectList(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); 66 | } 67 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/java/mybatis/mate/datascope/service/UserService.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import lombok.AllArgsConstructor; 6 | import mybatis.mate.databind.RequestDataTransfer; 7 | import mybatis.mate.datascope.entity.User; 8 | import mybatis.mate.datascope.mapper.UserMapper; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | @Service 15 | @AllArgsConstructor 16 | public class UserService { 17 | private UserMapper userMapper; 18 | 19 | public void dataScopeDefaultMethod() { 20 | IPage userPage = userMapper.page(Page.of(1, 10), "153"); 21 | System.out.println("total=" + userPage.getTotal()); 22 | } 23 | 24 | public void dataScope() { 25 | System.err.println("----- selectList ---- 使用类注解 "); 26 | userMapper.selectList(null).forEach(System.out::println); 27 | 28 | 29 | RequestDataTransfer.put("myParam", "这个参数可以动态的改变,在数据权限内容识别做更多的事情"); 30 | 31 | System.err.println("----- 自定义方法 selectTestList ---- 使用方法注解 "); 32 | Page page = new Page(1, 20); 33 | userMapper.selectTestList(page, 1L, "Jack").forEach(System.out::println); 34 | 35 | userMapper.selectTestJoin(page, 1L, "Jack").forEach(System.out::println); 36 | 37 | // 观察 sql 变化这个方法没有注解权限,使用类注解 38 | User user = userMapper.selectById(1L); 39 | user.setUsername("abc"); 40 | 41 | // 执行 processUpdate 方法 42 | userMapper.updateById(user); 43 | 44 | // 执行 processInsert 方法 45 | userMapper.insert(new User(6L, 1L, "hello", "15315336667")); 46 | 47 | // 执行 processDelete 方法 48 | userMapper.deleteById(6L); 49 | 50 | List ids = Arrays.asList(1L, 2L, 3L, 5L); 51 | 52 | // xml sql 53 | userMapper.selectDeptNamesByUserIds(ids, "o").forEach(System.out::println); 54 | 55 | // ignore dataScope 56 | userMapper.selectTestIgnoreDataScope(ids, "o").forEach(System.out::println); 57 | 58 | // use mapper dataScope 59 | userMapper.selectTestXmlSql(ids, "o").forEach(System.out::println); 60 | 61 | IPage userPage = userMapper.page(Page.of(1, 10), "153"); 62 | System.out.println("total=" + userPage.getTotal()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | data-locations: classpath:db/data-h2.sql 12 | mode: always 13 | 14 | mybatis-plus: 15 | mapper-locations: classpath:mapper/**/*Mapper.xml 16 | global-config: 17 | banner: false 18 | 19 | # Mybatis Mate 配置 20 | mybatis-mate: 21 | cert: 22 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 23 | grant: dGhpc0lzVGVzdExpY2Vuc2Uj5byg5LiJ 24 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 25 | 26 | # Logger Config 27 | logging: 28 | level: 29 | mybatis.mate: debug 30 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/resources/db/data-h2.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM user; 2 | DELETE FROM department; 3 | 4 | INSERT INTO user (id, department_id, username, mobile) VALUES 5 | (1, 1, 'Jack', '15315355555'), 6 | (2, 1, 'Jone', '15315399999'), 7 | (3, 3, 'Duo', '15315338888'), 8 | (4, 5, 'mali', '15315377777'), 9 | (5, 1, 'Tom', '15315336666'); 10 | 11 | INSERT INTO department (id, pid, name, sort) VALUES 12 | (1, 0, '研发中心', 0), 13 | (2, 1, '项目部', 3), 14 | (3, 2, '后端开发组', 2), 15 | (4, 2, '前端开发组', 2), 16 | (5, 1, '产品部', 1), 17 | (6, 1, '运维部', 0); 18 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | DROP TABLE IF EXISTS department; 3 | 4 | CREATE TABLE user 5 | ( 6 | id BIGINT(20) NOT NULL COMMENT '主键ID', 7 | department_id BIGINT(20) NOT NULL COMMENT '部门ID', 8 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 9 | mobile VARCHAR(11) NULL DEFAULT NULL COMMENT '手机号', 10 | PRIMARY KEY (id) 11 | ); 12 | 13 | CREATE TABLE department 14 | ( 15 | id BIGINT(20) NOT NULL COMMENT '主键ID', 16 | pid BIGINT(20) NOT NULL COMMENT '父ID', 17 | name VARCHAR(30) NULL DEFAULT NULL COMMENT '名称', 18 | sort int(11) NULL DEFAULT NULL COMMENT '排序', 19 | PRIMARY KEY (id) 20 | ); -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | select u.id,u.username,u.mobile from user u, department d where d.id = u.department_id and u.id in 7 | 8 | #{id} 9 | 10 | and u.username like CONCAT('%',#{username},'%') 11 | 12 | 13 | 16 | 17 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /mybatis-mate-datascope/src/test/java/mybatis/mate/datascope/DataScopeTest.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.datascope; 2 | 3 | import mybatis.mate.datascope.service.UserService; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | /** 11 | * 数据权限测试 12 | */ 13 | @RunWith(SpringRunner.class) 14 | @SpringBootTest 15 | public class DataScopeTest { 16 | @Autowired 17 | private UserService userService; 18 | 19 | @Test 20 | public void test() { 21 | // 查看控制台,输出执行 sql 语句 22 | userService.dataScope(); 23 | } 24 | 25 | @Test 26 | public void testDefault() { 27 | // default 方法无法拦截,可以通过重写父类方法间接解决 28 | userService.dataScopeDefaultMethod(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/build.gradle: -------------------------------------------------------------------------------- 1 | description "表结构自动维护 Mysql 示例" 2 | 3 | dependencies { 4 | implementation("mysql:mysql-connector-java") 5 | 6 | } 7 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-ddl-mysql 11 | 12 | 13 | 14 | mysql 15 | mysql-connector-java 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-maven-plugin 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/src/main/java/mybatis/mate/ddl/mysql/DdlMysqlApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.ddl.mysql; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DdlMysqlApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DdlMysqlApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/src/main/java/mybatis/mate/ddl/mysql/MysqlDdl.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.ddl.mysql; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.SimpleDdl; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | @Component 10 | public class MysqlDdl extends SimpleDdl { 11 | 12 | /** 13 | * 执行 SQL 脚本方式 14 | */ 15 | @Override 16 | public List getSqlFiles() { 17 | return Arrays.asList( 18 | // 测试存储过程 19 | "db/test_procedure.sql#$$", 20 | 21 | // 内置包方式 22 | "db/tag-schema.sql", 23 | 24 | // 文件绝对路径方式(修改为你电脑的地址) 25 | "D:\\IdeaProjects\\mybatis-mate-examples\\mybatis-mate-ddl-mysql\\src\\main\\resources\\db\\tag-data.sql" 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: com.mysql.cj.jdbc.Driver 5 | url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 6 | username: root 7 | 8 | # Mybatis Mate 配置 9 | mybatis-mate: 10 | cert: 11 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 12 | grant: thisIsTestLicense 13 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 14 | 15 | # Logger Config 16 | logging: 17 | level: 18 | mybatis.mate: debug 19 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/src/main/resources/db/tag-data.sql: -------------------------------------------------------------------------------- 1 | -- ---------------------------- 2 | -- Records of tag 3 | -- ---------------------------- 4 | INSERT INTO `tag` VALUES (1, 'Java', 0); 5 | INSERT INTO `tag` VALUES (2, 'JVM', 0); 6 | INSERT INTO `tag` VALUES (3, 'Golang', 1); 7 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/src/main/resources/db/tag-schema.sql: -------------------------------------------------------------------------------- 1 | SET NAMES utf8mb4; 2 | SET FOREIGN_KEY_CHECKS = 0; 3 | 4 | -- ---------------------------- 5 | -- Table structure for tag 6 | -- ---------------------------- 7 | DROP TABLE IF EXISTS `tag`; 8 | CREATE TABLE `tag` ( 9 | `id` int(11) NOT NULL AUTO_INCREMENT, 10 | `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '标签名字', 11 | `type` int(11) NULL DEFAULT NULL COMMENT '所属类别:0文章,1类别', 12 | PRIMARY KEY (`id`) USING BTREE 13 | ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '标签' ROW_FORMAT = Dynamic; 14 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-mysql/src/main/resources/db/test_procedure.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE PROCEDURE p_alter_table_column_add(tableName VARCHAR(200),columnName VARCHAR(200),sqlStr VARCHAR(1000)) 3 | BEGIN 4 | DECLARE Rows1 INT(10); 5 | SET Rows1=0; 6 | SELECT COUNT(*) INTO Rows1 FROM INFORMATION_SCHEMA.Columns WHERE table_schema= DATABASE() AND table_name=tableName AND column_name=columnName; 7 | 8 | IF (Rows1<=0) THEN 9 | SET sqlStr = CONCAT( 'ALTER TABLE ', tableName, ' ADD COLUMN ', columnName, ' ', sqlStr); 10 | END IF; 11 | 12 | IF (sqlStr!='') THEN 13 | SET @sql1 = sqlStr; 14 | PREPARE stmt1 FROM @SQL1; 15 | EXECUTE stmt1; 16 | END IF; 17 | END;$$ 18 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-oracle/build.gradle: -------------------------------------------------------------------------------- 1 | description "表结构自动维护 Mysql 示例" 2 | 3 | dependencies { 4 | implementation fileTree(dir: "libs", include: "*.jar") 5 | 6 | } 7 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-oracle/libs/ojdbc-11.2.0.3-jdk16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baomidou/mybatis-mate-examples/49536203f7240b13a95e5dbf5a6e82314bad515e/mybatis-mate-ddl-oracle/libs/ojdbc-11.2.0.3-jdk16.jar -------------------------------------------------------------------------------- /mybatis-mate-ddl-oracle/src/main/java/mybatis/mate/ddl/mysql/DdlOracleApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.ddl.mysql; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DdlOracleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DdlOracleApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-oracle/src/main/java/mybatis/mate/ddl/mysql/OracleDdl.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.ddl.mysql; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.SimpleDdl; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | @Component 10 | public class OracleDdl extends SimpleDdl { 11 | 12 | /** 13 | * 执行 SQL 脚本方式 14 | */ 15 | @Override 16 | public List getSqlFiles() { 17 | return Arrays.asList( 18 | // 内置包方式 19 | "db/tag-schema.sql", 20 | "db/tag-data.sql" 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-oracle/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: oracle.jdbc.driver.OracleDriver 5 | url: jdbc:oracle:thin:@47.104.207.160:1521:htxx 6 | username: zhgj 7 | password: zhgj 8 | 9 | 10 | # Mybatis Mate 配置 11 | mybatis-mate: 12 | cert: 13 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 14 | grant: thisIsTestLicense 15 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 16 | 17 | mybatis-plus: 18 | configuration: 19 | jdbc-type-for-null: 'null' 20 | 21 | # Logger Config 22 | logging: 23 | level: 24 | mybatis.mate: debug 25 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-oracle/src/main/resources/db/tag-data.sql: -------------------------------------------------------------------------------- 1 | 2 | -- ---------------------------- 3 | -- Records of "ZHGJ"."TAG" 4 | -- -------------------------- 5 | INSERT INTO "ZHGJ"."TAG" VALUES ('1', '小羊', '1'); 6 | INSERT INTO "ZHGJ"."TAG" VALUES ('2', '小兔', '2'); 7 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-oracle/src/main/resources/db/tag-schema.sql: -------------------------------------------------------------------------------- 1 | -- ---------------------------- 2 | -- Table structure for "ZHGJ"."TAG" 3 | -- ---------------------------- 4 | -- DROP TABLE "ZHGJ"."TAG"; 5 | CREATE TABLE "ZHGJ"."TAG" ( 6 | "id" NUMBER(20,0) VISIBLE NOT NULL, 7 | "name" NVARCHAR2(30) VISIBLE NOT NULL, 8 | "type" NUMBER(6,0) VISIBLE 9 | ) 10 | LOGGING 11 | NOCOMPRESS 12 | PCTFREE 10 13 | INITRANS 1 14 | STORAGE ( 15 | INITIAL 65536 16 | NEXT 1048576 17 | MINEXTENTS 1 18 | MAXEXTENTS 2147483645 19 | BUFFER_POOL DEFAULT 20 | ) 21 | PARALLEL 1 22 | NOCACHE 23 | DISABLE ROW MOVEMENT 24 | ; 25 | COMMENT ON COLUMN "ZHGJ"."TAG"."id" IS '主键 ID'; 26 | COMMENT ON COLUMN "ZHGJ"."TAG"."name" IS '名称'; 27 | COMMENT ON COLUMN "ZHGJ"."TAG"."type" IS '类别'; 28 | COMMENT ON TABLE "ZHGJ"."TAG" IS '标签'; 29 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-postgres/build.gradle: -------------------------------------------------------------------------------- 1 | description "表结构自动维护 PostgreSQL 示例" 2 | 3 | dependencies { 4 | implementation("org.postgresql:postgresql") 5 | 6 | } 7 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-postgres/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-ddl-postgres 11 | 12 | 13 | 14 | org.postgresql 15 | postgresql 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-maven-plugin 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-postgres/src/main/java/mybatis/mate/ddl/postgres/DdlPostgresApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.ddl.postgres; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DdlPostgresApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DdlPostgresApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-postgres/src/main/java/mybatis/mate/ddl/postgres/PostgresDdl.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.ddl.postgres; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.SimpleDdl; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | @Component 10 | public class PostgresDdl extends SimpleDdl { 11 | 12 | /** 13 | * 执行 SQL 脚本方式 14 | */ 15 | @Override 16 | public List getSqlFiles() { 17 | return Arrays.asList( 18 | // 内置包方式 19 | "db/tag-schema.sql", 20 | 21 | // 文件绝对路径方式(修改为你电脑的地址) 22 | "D:\\IdeaProjects\\mybatis-mate-examples\\mybatis-mate-ddl-postgres\\src\\main\\resources\\db\\tag-data.sql" 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-postgres/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.postgresql.Driver 5 | url: jdbc:postgresql://localhost:5432/test 6 | username: postgres 7 | password: 123456 8 | 9 | # Mybatis Mate 配置 10 | mybatis-mate: 11 | cert: 12 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 13 | grant: thisIsTestLicense 14 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 15 | 16 | # Logger Config 17 | logging: 18 | level: 19 | mybatis.mate: debug 20 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-postgres/src/main/resources/db/tag-data.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM tag; 2 | INSERT INTO "public"."tag" VALUES (1, '小羊', 1),(2, '小兔', 2); 3 | -------------------------------------------------------------------------------- /mybatis-mate-ddl-postgres/src/main/resources/db/tag-schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS "public"."tag" ( 2 | "id" int8 NOT NULL, 3 | "name" varchar(30) COLLATE "pg_catalog"."default" NOT NULL, 4 | "type" int2 DEFAULT 1 5 | ); 6 | COMMENT ON COLUMN "public"."tag"."id" IS '主键 ID'; 7 | COMMENT ON COLUMN "public"."tag"."name" IS '名称'; 8 | COMMENT ON COLUMN "public"."tag"."type" IS '类别'; 9 | COMMENT ON TABLE "public"."tag" IS '标签'; 10 | -------------------------------------------------------------------------------- /mybatis-mate-dict/build.gradle: -------------------------------------------------------------------------------- 1 | description "字段数据字典自动映射示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | 6 | testImplementation("org.springframework.boot:spring-boot-starter-test") 7 | testImplementation("junit:junit") 8 | } 9 | -------------------------------------------------------------------------------- /mybatis-mate-dict/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-dict 11 | 12 | 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-maven-plugin 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/java/mybatis/mate/dict/DictApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DictApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DictApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/java/mybatis/mate/dict/config/BindType.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.config; 2 | 3 | public interface BindType { 4 | String USER_SEX = "user_sex"; 5 | String USER_STATUS = "user_status"; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/java/mybatis/mate/dict/config/DataBind.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import mybatis.mate.annotation.FieldBind; 5 | import mybatis.mate.dict.entity.StatusEnum; 6 | import mybatis.mate.dict.mapper.UserMapper; 7 | import mybatis.mate.sets.IDataBind; 8 | import org.apache.ibatis.reflection.MetaObject; 9 | import org.springframework.context.ApplicationContext; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.Map; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | 15 | @Component 16 | @AllArgsConstructor 17 | public class DataBind implements IDataBind { 18 | private ApplicationContext applicationContext; 19 | 20 | /** 21 | * 从数据库或缓存中获取 22 | */ 23 | private Map SEX_MAP = new ConcurrentHashMap() {{ 24 | put("0", "女"); 25 | put("1", "男"); 26 | }}; 27 | 28 | /** 29 | * 设置元数据对象
30 | * 根据源对象映射绑定指定属性(自行处理缓存逻辑) 31 | * 32 | * @param fieldBind 数据绑定注解 33 | * @param fieldValue 属性值 34 | * @param metaObject 元数据对象 {@link MetaObject} 35 | * @return 36 | */ 37 | @Override 38 | public void setMetaObject(FieldBind fieldBind, Object fieldValue, MetaObject metaObject) { 39 | 40 | // 调用数据库获取数据,这里采用 getBean 方式避免 spring boot 检查循环依赖问题 41 | Long userCount = applicationContext.getBean(UserMapper.class).selectCount(null); 42 | System.out.println("userCount=" + userCount); 43 | 44 | System.err.println("字段类型:" + fieldBind.type() + ",绑定属性值:" + fieldValue); 45 | // 数据库中数据转换 46 | if (BindType.USER_SEX.equals(fieldBind.type())) { 47 | metaObject.setValue(fieldBind.target(), SEX_MAP.get(String.valueOf(fieldValue))); 48 | } 49 | // 枚举数据转换 50 | else if (BindType.USER_STATUS.equals(fieldBind.type())) { 51 | metaObject.setValue(fieldBind.target(), StatusEnum.get((Integer) fieldValue)); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/java/mybatis/mate/dict/config/JsonBindStrategy.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.config; 2 | 3 | import mybatis.mate.databind.IJsonBindStrategy; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.function.Function; 9 | 10 | @Component 11 | public class JsonBindStrategy implements IJsonBindStrategy { 12 | 13 | public interface Type { 14 | String departmentRole = "departmentRole"; 15 | 16 | } 17 | 18 | @Override 19 | public Map>> getStrategyFunctionMap() { 20 | return new HashMap>>(16) { 21 | { 22 | // 注入虚拟节点,绑定部门角色信息 23 | put(Type.departmentRole, (obj) -> new HashMap(2) {{ 24 | put("departmentName", "研发部"); 25 | put("roleName", "经理"); 26 | }}); 27 | } 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/java/mybatis/mate/dict/entity/StatusEnum.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.entity; 2 | 3 | public enum StatusEnum { 4 | online(0, "在线"), 5 | offline(1, "离线"), 6 | unknown(2, "未知"); 7 | 8 | private int status; 9 | private String desc; 10 | 11 | StatusEnum(final int status, final String desc) { 12 | this.status = status; 13 | this.desc = desc; 14 | } 15 | 16 | public static StatusEnum get(int status) { 17 | StatusEnum[] statusEnums = StatusEnum.values(); 18 | for (StatusEnum se : statusEnums) { 19 | if (se.status == status) { 20 | return se; 21 | } 22 | } 23 | return StatusEnum.unknown; 24 | } 25 | 26 | public String getDesc() { 27 | return desc; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/java/mybatis/mate/dict/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import mybatis.mate.annotation.FieldBind; 8 | import mybatis.mate.dict.config.BindType; 9 | 10 | @Getter 11 | @Setter 12 | @ToString 13 | public class User { 14 | private Long id; 15 | private String username; 16 | 17 | /** 18 | * type 绑定类型 ,target 目标显示属性 19 | */ 20 | @FieldBind(type = BindType.USER_SEX, target = "sexText") 21 | private Integer sex; 22 | 23 | // 绑定显示属性,非表字典(排除) 24 | @TableField(exist = false) 25 | private String sexText; 26 | 27 | @FieldBind(type = BindType.USER_STATUS, target = "statusEnum") 28 | private Integer status; 29 | 30 | @TableField(exist = false) 31 | private StatusEnum statusEnum; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/java/mybatis/mate/dict/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.dict.entity.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface UserMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | data-locations: classpath:db/data-h2.sql 12 | mode: always 13 | 14 | # Mybatis Mate 配置 15 | mybatis-mate: 16 | cert: 17 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 18 | grant: thisIsTestLicense 19 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 20 | 21 | # Logger Config 22 | logging: 23 | level: 24 | mybatis.mate: debug 25 | -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/resources/db/data-h2.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM user; 2 | 3 | INSERT INTO user (id, username, sex, status) VALUES (1, 'Jone', 1, 1), (2, 'Jack', 0, 0), (3, 'Tom', 1, 1); -------------------------------------------------------------------------------- /mybatis-mate-dict/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | 3 | CREATE TABLE user 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 7 | sex INT(2) NULL DEFAULT NULL COMMENT '性别', 8 | status INT(2) NULL DEFAULT NULL COMMENT '状态', 9 | PRIMARY KEY (id) 10 | ); -------------------------------------------------------------------------------- /mybatis-mate-dict/src/test/java/mybatis/mate/dict/DictTest.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict; 2 | 3 | import com.baomidou.mybatisplus.core.toolkit.IdWorker; 4 | import mybatis.mate.dict.entity.User; 5 | import mybatis.mate.dict.mapper.UserMapper; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | /** 15 | * 字典测试 16 | */ 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class DictTest { 20 | @Autowired 21 | private UserMapper mapper; 22 | 23 | @Test 24 | public void test() { 25 | User user = new User(); 26 | user.setId(IdWorker.getId()); 27 | user.setUsername("小羊肖恩"); 28 | user.setSex(1); 29 | user.setStatus(1); 30 | assertThat(mapper.insert(user)).isGreaterThan(0); 31 | assertThat(user.getId()).isNotNull(); 32 | System.out.println(mapper.selectById(user.getId())); 33 | mapper.selectList(null).forEach(System.out::println); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/attr.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : mysql 5 | Source Server Type : MySQL 6 | Source Server Version : 80016 7 | Source Host : localhost:3306 8 | Source Schema : test 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 80016 12 | File Encoding : 65001 13 | 14 | Date: 01/09/2021 23:44:27 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for attr 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `attr`; 24 | CREATE TABLE `attr` ( 25 | `attr_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 26 | `attr_title` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL, 27 | `email` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL, 28 | `mobile` varchar(192) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL 29 | ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 30 | 31 | -- ---------------------------- 32 | -- Records of attr 33 | -- ---------------------------- 34 | INSERT INTO `attr` VALUES ('100001', '8A48C76F86AC19D8E5AD7D348235CC0094E03CCB174206A3E9F50FA4104F9468D03D6C297E7B9BC2F3BDC8B3AE8DD630', '7D433C68FDB065582974922A9DF39CBF', 'B27C6F848CAC03A1DAAF9A4C5E9C9D77'); 35 | INSERT INTO `attr` VALUES ('100002', '5C1B8780CD5E127C0B2105DFB367524BD57E9C19BE6818378F3D9FCFABDAD9B7DA77F3A81109CC126471EFBB4B4268C7', 'A56BC902A70C6E5C765BB47D07D766F2', '34FF3B1A162FDF8565E0A1996AEEEC53'); 36 | INSERT INTO `attr` VALUES ('100003', '81CE50C96117CAD14A9719D2BE6886A50C5831A49D02AF13FB62E420BCE7003D', '7D433C68FDB065582974922A9DF39CBF', 'B27C6F848CAC03A1DAAF9A4C5E9C9D77'); 37 | INSERT INTO `attr` VALUES ('100004', '764461734689F4AE229708E421A83170F8B646FA59291FC64113D6F109C3FDD3', 'A56BC902A70C6E5C765BB47D07D766F2', '507F906014308FFAEE4E48900B154806'); 38 | INSERT INTO `attr` VALUES ('100005', 'E6DCCAA6C52A2A539E988142FB73C36B374ABAED11AB2FEDC4BA0CC323915BDE', '7D433C68FDB065582974922A9DF39CBF', 'B27C6F848CAC03A1DAAF9A4C5E9C9D77'); 39 | INSERT INTO `attr` VALUES ('100012', 'E4A66BEA17412E456CF3B1114BB10FC465453CADB20357841FADCFC052B1DE9F', 'A56BC902A70C6E5C765BB47D07D766F2', '34FF3B1A162FDF8565E0A1996AEEEC53'); 40 | INSERT INTO `attr` VALUES ('100013', '370A9B21DD47D9D43D36E6851C33DC5EDA77F3A81109CC126471EFBB4B4268C7', '7D433C68FDB065582974922A9DF39CBF', 'B27C6F848CAC03A1DAAF9A4C5E9C9D77'); 41 | INSERT INTO `attr` VALUES ('100015', '3D9D0DF1B6E26FD8693AD06F37DA61C729E1DC76E6FBCE99EA225A57877823A2', '3C72816B56ABE4D1E1E2B1490358CBE9', '507F906014308FFAEE4E48900B154806'); 42 | INSERT INTO `attr` VALUES ('100016', '7C277D4462B817FBA67B9E7032797066DD4EEE84C0B9193A30E93DE1E79947C498DF434333FBD69D6FCE0A154D87EDD3', '7D433C68FDB065582974922A9DF39CBF', 'B27C6F848CAC03A1DAAF9A4C5E9C9D77'); 43 | INSERT INTO `attr` VALUES ('100017', '8A91347595EBE8A94AD1009C545805AF8EC464394FA266E23E50FB232A3E4F73', '3C72816B56ABE4D1E1E2B1490358CBE9', '507F906014308FFAEE4E48900B154806'); 44 | INSERT INTO `attr` VALUES ('100028', '78B3148C751A99B9C2A00EFBF4BF4A1EB01DFD50D70C639D9D02F04B09508C31255174AAB517F3013D48CB48F5BCD52C', '7D433C68FDB065582974922A9DF39CBF', 'B27C6F848CAC03A1DAAF9A4C5E9C9D77'); 45 | INSERT INTO `attr` VALUES ('100031', '3379E727C6CDDB86C027DB2F79CEFCF8AC28E776F4F250932BD58629AD2B3528', '3C72816B56ABE4D1E1E2B1490358CBE9', '507F906014308FFAEE4E48900B154806'); 46 | INSERT INTO `attr` VALUES ('10085', NULL, NULL, NULL); 47 | INSERT INTO `attr` VALUES ('10086', NULL, '3C72816B56ABE4D1E1E2B1490358CBE9', NULL); 48 | INSERT INTO `attr` VALUES ('10087', NULL, '3C72816B56ABE4D1E1E2B1490358CBE9', NULL); 49 | 50 | SET FOREIGN_KEY_CHECKS = 1; 51 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/build.gradle: -------------------------------------------------------------------------------- 1 | description "字段加解密示例" 2 | 3 | dependencies { 4 | implementation("mysql:mysql-connector-java") 5 | 6 | // 默认加密库,自定义加密可以不依赖 7 | implementation("org.jasypt:jasypt") 8 | 9 | testImplementation("org.springframework.boot:spring-boot-starter-test") 10 | testImplementation("junit:junit") 11 | } 12 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-encrypt-mysql-aes 11 | 12 | 13 | 14 | mysql 15 | mysql-connector-java 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-maven-plugin 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/src/main/java/mybatis/mate/sm/mysql/aes/EncryptMysqlAesApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm.mysql.aes; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class EncryptMysqlAesApplication { 8 | 9 | // 测试访问 http://localhost:8080/test 10 | // 测试访问 http://localhost:8080/test2 11 | public static void main(String[] args) { 12 | SpringApplication.run(EncryptMysqlAesApplication.class, args); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/src/main/java/mybatis/mate/sm/mysql/aes/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm.mysql.aes.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; 4 | import lombok.AllArgsConstructor; 5 | import mybatis.mate.sm.mysql.aes.entity.ComAttr; 6 | import mybatis.mate.sm.mysql.aes.mapper.ComAttrMapper; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import java.util.HashMap; 11 | import java.util.List; 12 | 13 | /** 14 | * 测试控制器 15 | */ 16 | @RestController 17 | @AllArgsConstructor 18 | public class TestController { 19 | private ComAttrMapper comAttrMapper; 20 | 21 | @GetMapping("/test") 22 | public HashMap test() { 23 | String testId = "10086"; 24 | ComAttr comAttr = comAttrMapper.selectById(testId); 25 | if (null == comAttr) { 26 | comAttr = new ComAttr(testId, "测试插入逻辑", "abc@163.com", "15312321111"); 27 | comAttrMapper.insert(comAttr); 28 | } 29 | System.err.println(comAttr); 30 | 31 | ComAttr comAttr1 = new LambdaQueryChainWrapper<>(comAttrMapper).eq(ComAttr::getAttrId, testId).one(); 32 | System.out.println(comAttr1.getAttrTitle()); 33 | 34 | //输出的attrTitle属性性为解密后的 35 | return new HashMap(2) {{ 36 | put("dbList", comAttrMapper.selectList(null)); 37 | put("voList", comAttrMapper.selectVO()); 38 | }}; 39 | } 40 | 41 | @GetMapping("/test2") 42 | public List test2() { 43 | return comAttrMapper.selectVO2(); 44 | } 45 | } -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/src/main/java/mybatis/mate/sm/mysql/aes/entity/AttrVO.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm.mysql.aes.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import mybatis.mate.annotation.FieldEncrypt; 6 | 7 | import java.util.Date; 8 | 9 | @Getter 10 | @Setter 11 | public class AttrVO extends ComAttr { 12 | 13 | // 指定密钥(子类注解会覆盖父类) 14 | @FieldEncrypt(password = "123456789") 15 | private String mobile; 16 | 17 | private Date time; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/src/main/java/mybatis/mate/sm/mysql/aes/entity/ComAttr.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 os-parent Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mybatis.mate.sm.mysql.aes.entity; 17 | 18 | import com.baomidou.mybatisplus.annotation.TableId; 19 | import com.baomidou.mybatisplus.annotation.TableName; 20 | import com.baomidou.mybatisplus.extension.activerecord.Model; 21 | import lombok.*; 22 | import lombok.experimental.Tolerate; 23 | import mybatis.mate.annotation.FieldEncrypt; 24 | 25 | import java.io.Serializable; 26 | 27 | /** 28 | *

29 | * 30 | *

31 | * 32 | * @author Clark 33 | * @date 2021-08-26 34 | */ 35 | @Builder 36 | @Getter 37 | @Setter 38 | @ToString 39 | @AllArgsConstructor 40 | @TableName("attr") 41 | public class ComAttr extends Model { 42 | 43 | private static final long serialVersionUID = 1L; 44 | @Tolerate 45 | public ComAttr() {} 46 | 47 | @TableId 48 | private String attrId; 49 | 50 | // 不指定 (encryptor = AesEncryptor.class) 会走全局处理器 51 | // @FieldEncrypt(encryptor = AesEncryptor.class) 52 | @FieldEncrypt 53 | private String attrTitle; 54 | 55 | @FieldEncrypt 56 | private String email; 57 | 58 | // 指定密钥 59 | @FieldEncrypt(password = "123456789") 60 | private String mobile; 61 | 62 | @Override 63 | public Serializable pkVal() { 64 | return this.attrId; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/src/main/java/mybatis/mate/sm/mysql/aes/mapper/ComAttrMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm.mysql.aes.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.sm.mysql.aes.entity.AttrVO; 5 | import mybatis.mate.sm.mysql.aes.entity.ComAttr; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Select; 8 | 9 | import java.util.List; 10 | 11 | @Mapper 12 | public interface ComAttrMapper extends BaseMapper { 13 | 14 | /** 15 | * 处理复杂情况 16 | */ 17 | @Select("SELECT attr_id,email,mobile,(SELECT CURRENT_DATE FROM DUAL) time FROM attr") 18 | List selectVO(); 19 | 20 | @Select("SELECT email FROM attr") 21 | List selectVO2(); 22 | } 23 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-mysql-aes/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | logging: 4 | level: 5 | org.springframework: info 6 | com.onestop: debug 7 | # 数据源 8 | spring: 9 | datasource: 10 | driver-class-name: com.mysql.cj.jdbc.Driver 11 | url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true 12 | username: root 13 | password: 14 | 15 | mybatis-plus: 16 | # typeAliasesPackage: com.onestop.**.model.entity 17 | # mapper-locations: classpath:/mapper/*Mapper.xml 18 | configuration: 19 | #驼峰下划线转换 20 | map-underscore-to-camel-case: true 21 | global-config: 22 | db-config: 23 | #逻辑删除配置(下面3个配置) 24 | logic-delete-field: deleted 25 | logic-delete-value: 1 26 | logic-not-delete-value: 0 27 | #表名、是否使用下划线命名,默认数据库表使用下划线命名 28 | table-underline: true 29 | 30 | # Mybatis Mate 配置 31 | mybatis-mate: 32 | cert: 33 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 34 | grant: thisIsTestLicense 35 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 36 | # 全局配置加密算法密钥 37 | encryptor: 38 | # 随机字符串作为密钥即可 39 | password: qmh9MK4KsZY8FnqkJYk8tzgc0H 40 | algorithm: AES 41 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/build.gradle: -------------------------------------------------------------------------------- 1 | description "字段国密 sm2 sm3 sm4 加解密示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | 6 | // 默认加密库,自定义加密可以不依赖 7 | implementation("org.jasypt:jasypt") 8 | // sm4 依赖加密库 9 | implementation("org.bouncycastle:bctls-jdk15on:1.69") 10 | 11 | testImplementation("org.springframework.boot:spring-boot-starter-test") 12 | testImplementation("junit:junit") 13 | } 14 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-encrypt-sm2-sm3-sm4 11 | 12 | 13 | 14 | org.bouncycastle 15 | bctls-jdk15on 16 | 1.69 17 | 18 | 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-maven-plugin 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/main/java/mybatis/mate/sm/EncryptApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class EncryptApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(EncryptApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/main/java/mybatis/mate/sm/config/DataBind.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm.config; 2 | 3 | import mybatis.mate.annotation.FieldBind; 4 | import mybatis.mate.sets.IDataBind; 5 | import org.apache.ibatis.reflection.MetaObject; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class DataBind implements IDataBind { 10 | 11 | /** 12 | * 设置元数据对象
13 | * 根据源对象映射绑定指定属性(自行处理缓存逻辑) 14 | * 15 | * @param fieldBind 数据绑定注解 16 | * @param fieldValue 属性值 17 | * @param metaObject 元数据对象 {@link MetaObject} 18 | * @return 19 | */ 20 | @Override 21 | public void setMetaObject(FieldBind fieldBind, Object fieldValue, MetaObject metaObject) { 22 | System.err.println("字段类型:" + fieldBind.type() + ",绑定属性值:" + fieldValue); 23 | metaObject.setValue(fieldBind.target(), "bind_md_" + fieldValue); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/main/java/mybatis/mate/sm/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.*; 5 | import mybatis.mate.annotation.Algorithm; 6 | import mybatis.mate.annotation.FieldBind; 7 | import mybatis.mate.annotation.FieldEncrypt; 8 | import mybatis.mate.encrypt.KeyGenerator; 9 | 10 | @Getter 11 | @Setter 12 | @ToString 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class User { 16 | private Long id; 17 | private String username; 18 | 19 | // 指定加密算法 20 | @FieldEncrypt(algorithm = Algorithm.PBEWithMD5AndDES) 21 | private String password; 22 | 23 | /** 24 | * 注意 SM2 SM3 SM4 加密算法必须依赖 bouncycastle 库, 25 | */ 26 | @FieldEncrypt(algorithm = Algorithm.SM4) 27 | private String email; 28 | 29 | /** 30 | * 非对称加密需要全局指定公钥私钥 31 | * {@link KeyGenerator#generateSM2Keys()} 这个生成密钥对 0 公钥 1 私钥 32 | */ 33 | @FieldEncrypt(algorithm = Algorithm.SM2) 34 | private String sm2; 35 | 36 | /** 37 | * 加密数据绑定混合 38 | */ 39 | @FieldEncrypt(algorithm = Algorithm.SM3) 40 | @FieldBind(type = "test_bind", target = "sm3Text") 41 | private String sm3; 42 | 43 | @TableField(exist = false) 44 | private String sm3Text; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/main/java/mybatis/mate/sm/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.sm.entity.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface UserMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | mode: always 12 | 13 | # Mybatis Mate 配置 14 | mybatis-mate: 15 | cert: 16 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 17 | grant: thisIsTestLicense 18 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 19 | encryptor: 20 | password: 4861bbb8e07a8673f67781103220c400 21 | publicKey: MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEPgMdGnjGad3tvzGI7Rlidr0XS/DdKGjLO2zxLPfYxSqHEi77mO4UWdnv0QEZfPN7HrskYFIleM9pCDy/jahVyQ== 22 | privateKey: MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg5udCqOiq4/LDLvV59YldSqCzGFfPmzhua8BQ7uribGOgCgYIKoEcz1UBgi2hRANCAAQ+Ax0aeMZp3e2/MYjtGWJ2vRdL8N0oaMs7bPEs99jFKocSLvuY7hRZ2e/RARl883seuyRgUiV4z2kIPL+NqFXJ 23 | 24 | mybatis-plus: 25 | mapper-locations: classpath:/mapper/*Mapper.xml 26 | 27 | # Logger Config 28 | logging: 29 | level: 30 | mybatis.mate: debug 31 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | 3 | CREATE TABLE user 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 7 | password VARCHAR(255) NULL DEFAULT NULL COMMENT '密码', 8 | email VARCHAR(255) NULL DEFAULT NULL COMMENT '邮箱', 9 | sm2 VARCHAR(800) NULL DEFAULT NULL COMMENT '国密SM2非对称算法', 10 | sm3 VARCHAR(255) NULL DEFAULT NULL COMMENT '国密SM3签名算法', 11 | PRIMARY KEY (id) 12 | ); -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/main/resources/sm4.js: -------------------------------------------------------------------------------- 1 | window.sm4=function(r){function n(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return r[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};return n.m=r,n.c=t,n.d=function(r,t,e){n.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:e})},n.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(t,"a",t),t},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n(n.s=8)}({8:function(r,n,t){"use strict";function e(r){if(Array.isArray(r)){for(var n=0,t=Array(r.length);n>>6),n.push(128|63&o)):(n.push(224|o>>>12),n.push(128|o>>>6&63),n.push(128|63&o))}return n}function f(r){for(var n=[],t=0,e=r.length;t=224&&r[t]<=239?(n.push(String.fromCharCode(((15&r[t])<<12)+((63&r[t+1])<<6)+(63&r[t+2]))),t+=2):r[t]>=192&&r[t]<=223?(n.push(String.fromCharCode(((31&r[t])<<6)+(63&r[t+1]))),t++):n.push(String.fromCharCode(r[t]));return n.join("")}function a(r,n){return r<>>32-n}function c(r){return(255&w[r>>>24&255])<<24|(255&w[r>>>16&255])<<16|(255&w[r>>>8&255])<<8|255&w[255&r]}function s(r){return r^a(r,2)^a(r,10)^a(r,18)^a(r,24)}function p(r){return r^a(r,13)^a(r,23)}function h(r,n,t){for(var e=new Array(4),o=new Array(4),u=0;u<4;u++)o[0]=255&r[0+4*u],o[1]=255&r[1+4*u],o[2]=255&r[2+4*u],o[3]=255&r[3+4*u],e[u]=o[0]<<24|o[1]<<16|o[2]<<8|o[3];for(var i,f=0;f<32;f+=4)i=e[1]^e[2]^e[3]^t[f+0],e[0]^=s(c(i)),i=e[2]^e[3]^e[0]^t[f+1],e[1]^=s(c(i)),i=e[3]^e[0]^e[1]^t[f+2],e[2]^=s(c(i)),i=e[0]^e[1]^e[2]^t[f+3],e[3]^=s(c(i));for(var a=0;a<16;a+=4)n[a]=e[3-a/4]>>>24&255,n[a+1]=e[3-a/4]>>>16&255,n[a+2]=e[3-a/4]>>>8&255,n[a+3]=255&e[3-a/4]}function v(r,n,t){for(var e=new Array(4),o=new Array(4),u=0;u<4;u++)o[0]=255&r[0+4*u],o[1]=255&r[1+4*u],o[2]=255&r[2+4*u],o[3]=255&r[3+4*u],e[u]=o[0]<<24|o[1]<<16|o[2]<<8|o[3];e[0]^=2746333894,e[1]^=1453994832,e[2]^=1736282519,e[3]^=2993693404;for(var i,f=0;f<32;f+=4)i=e[1]^e[2]^e[3]^A[f+0],n[f+0]=e[0]^=p(c(i)),i=e[2]^e[3]^e[0]^A[f+1],n[f+1]=e[1]^=p(c(i)),i=e[3]^e[0]^e[1]^A[f+2],n[f+2]=e[2]^=p(c(i)),i=e[0]^e[1]^e[2]^A[f+3],n[f+3]=e[3]^=p(c(i));if(t===g)for(var a,s=0;s<16;s++)a=n[s],n[s]=n[31-s],n[31-s]=a}function l(r,n,t){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},c=a.padding,s=void 0===c?"pkcs#5":c,p=(a.mode,a.output),l=void 0===p?"string":p;if("string"==typeof n&&(n=o(n)),16!==n.length)throw new Error("key is invalid");if(r="string"==typeof r?t!==g?i(r):o(r):[].concat(e(r)),"pkcs#5"===s&&t!==g)for(var w=d-r.length%d,A=0;A=d;){var j=r.slice(b,b+16),k=new Array(16);h(j,k,m);for(var S=0;S 2 | 3 | 4 | 5 | SM4加解密 6 | 7 | 8 | 打开控制台,查看结果 9 |
脚本来自:https://github.com/JuneAndGreen/sm-crypto 10 | 11 | 33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt-sm2-sm3-sm4/src/test/java/mybatis/mate/sm/EncryptTest.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sm; 2 | 3 | import mybatis.mate.encrypt.GMEncryptor; 4 | import mybatis.mate.encrypt.KeyGenerator; 5 | import mybatis.mate.sm.entity.User; 6 | import mybatis.mate.sm.mapper.UserMapper; 7 | import org.junit.Test; 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | 14 | import java.nio.charset.StandardCharsets; 15 | import java.security.PrivateKey; 16 | import java.security.PublicKey; 17 | import java.util.Base64; 18 | import java.util.List; 19 | 20 | /** 21 | * 国密 SM2 SM3 SM4 测试 22 | */ 23 | @RunWith(SpringRunner.class) 24 | @SpringBootTest 25 | public class EncryptTest { 26 | @Autowired 27 | private UserMapper mapper; 28 | 29 | @Test 30 | public void test() { 31 | User user = new User(1L, "hi china", "123456", "asd@qq.com", "asd", "asd", null); 32 | Assertions.assertEquals(1, mapper.insert(user)); 33 | System.err.println("加密内容:" + user); 34 | user = mapper.selectById(user.getId()); 35 | System.err.println("查询数据库内容:" + user); 36 | Assertions.assertEquals("asd@qq.com", user.getEmail()); 37 | Assertions.assertEquals("asd", user.getSm2()); 38 | Assertions.assertEquals(1, mapper.insert(new User(2L, "hi mp", 39 | "123456", "mp@qq.com", "mp", "mp", null))); 40 | List userList = mapper.selectList(null); 41 | Assertions.assertEquals(userList.size(), 2); 42 | for (User _user : userList) { 43 | Assertions.assertEquals("bind_md_" + _user.getSm3(), _user.getSm3Text()); 44 | if (_user.getId().equals(1L)) { 45 | Assertions.assertEquals("asd@qq.com", _user.getEmail()); 46 | } else if (_user.getId().equals(2L)) { 47 | Assertions.assertEquals("mp@qq.com", _user.getEmail()); 48 | } 49 | } 50 | } 51 | 52 | 53 | @Test 54 | public void sm2Test() throws Exception { 55 | final String test = "hi 测试数据。。.."; 56 | System.out.println("原始数据:" + test); 57 | 58 | // 生成公私钥对 59 | String[] keys = KeyGenerator.generateSM2Keys(); 60 | System.out.println("公钥:" + keys[0]); 61 | System.out.println(); 62 | PublicKey publicKey = KeyGenerator.createPublicKey(keys[0]); 63 | System.out.println("私钥:" + keys[1]); 64 | System.out.println(); 65 | PrivateKey privateKey = KeyGenerator.createPrivateKey(keys[1]); 66 | 67 | // 加解密测试 68 | byte[] encrypt = GMEncryptor.sm2Encrypt(test.getBytes(), publicKey); 69 | String encryptBase64Str = Base64.getEncoder().encodeToString(encrypt); 70 | System.out.println("加密数据:" + encryptBase64Str); 71 | System.out.println("等效于这样加密数据:" + GMEncryptor.sm2Encrypt(test, keys[0])); 72 | 73 | byte[] decrypt = GMEncryptor.sm2Decrypt(encrypt, privateKey); 74 | String decryptStr = new String(decrypt); 75 | System.out.println("解密数据:" + decryptStr); 76 | Assertions.assertEquals(GMEncryptor.sm2Decrypt(encryptBase64Str, keys[1]), decryptStr); 77 | 78 | byte[] sign = GMEncryptor.sm2SignByPrivateKey(test.getBytes(), privateKey); 79 | System.out.println("数据签名:" + Base64.getEncoder().encodeToString(sign)); 80 | 81 | boolean b = GMEncryptor.sm2VerifyByPublicKey(test.getBytes(), publicKey, sign); 82 | System.out.println("数据验签:" + b); 83 | } 84 | 85 | @Test 86 | public void sm3Test() { 87 | Assertions.assertEquals("96f565b02cb226202c6863dcf12bbb78b40d16e96eda1f100ddf9b33aee98488", 88 | GMEncryptor.sm3digest("国密 SM3 摘要算法".getBytes(StandardCharsets.UTF_8))); 89 | } 90 | 91 | @Test 92 | public void sm4Test() throws Exception { 93 | final String key = KeyGenerator.generateSM4Key(); 94 | System.err.println("加密 KEY = " + key); 95 | 96 | final String data = "国密 SM4 分组密码算法"; 97 | String output = GMEncryptor.sm4Encrypt(key, data); 98 | System.err.println("SM4 算法加密:" + output); 99 | Assertions.assertEquals(data, GMEncryptor.sm4Decrypt(key, output)); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/build.gradle: -------------------------------------------------------------------------------- 1 | description "字段加解密示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | 6 | // 默认加密库,自定义加密可以不依赖 7 | implementation("org.jasypt:jasypt") 8 | 9 | testImplementation("org.springframework.boot:spring-boot-starter-test") 10 | testImplementation("junit:junit") 11 | } 12 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-encrypt 11 | 12 | 13 | 14 | org.jasypt 15 | jasypt 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-maven-plugin 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/EncryptApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class EncryptApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(EncryptApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/config/CustomEncryptor.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.config; 2 | 3 | import mybatis.mate.annotation.Algorithm; 4 | import mybatis.mate.encrypt.IEncryptor; 5 | import org.apache.ibatis.reflection.MetaObject; 6 | 7 | // 自定义加密算法,这里为开启使用默认加密库 @Component 注解必须放在 spring 能够扫描到的目录 8 | //@Component 9 | public class CustomEncryptor implements IEncryptor { 10 | 11 | /** 12 | * 加密 13 | * 14 | * @param algorithm 算法 15 | * @param password 密码(对称加密算法密钥) 16 | * @param plaintext 明文 17 | * @param publicKey 非对称加密算法(公钥) 18 | * @param metaObject {@link org.apache.ibatis.reflection.MetaObject} 19 | * @return 20 | */ 21 | @Override 22 | public String encrypt(Algorithm algorithm, String password, String publicKey, 23 | String plaintext, Object metaObject) { 24 | if (metaObject instanceof MetaObject) { 25 | MetaObject _metaObject = ((MetaObject) metaObject); 26 | // 获取待加密对象 name 属性值,注意 src 是注解属性值框架层已经取出来了,这里是查询行对象任意值获取 27 | _metaObject.getValue("name"); 28 | } 29 | return "加密返回"; 30 | } 31 | 32 | /** 33 | * 解密 34 | * 35 | * @param algorithm 算法 36 | * @param password 密码(对称加密算法密钥) 37 | * @param encrypt 密文 38 | * @param privateKey 非对称加密算法(私钥) 39 | * @param metaObject {@link org.apache.ibatis.reflection.MetaObject} 40 | * @return 41 | */ 42 | @Override 43 | public String decrypt(Algorithm algorithm, String password, String privateKey, 44 | String encrypt, Object metaObject) { 45 | if (metaObject instanceof MetaObject) { 46 | MetaObject _metaObject = ((MetaObject) metaObject); 47 | // 获取待解密对象 name 属性值,注意 encrypt 是注解属性值框架层已经取出来了,这里是查询行对象任意值获取 48 | _metaObject.getValue("name"); 49 | } 50 | return "解密返回"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/config/MyEncryptor.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.config; 2 | 3 | import mybatis.mate.annotation.Algorithm; 4 | import mybatis.mate.encrypt.DefaultEncryptor; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class MyEncryptor extends DefaultEncryptor { 9 | 10 | /** 11 | * 加密 12 | * 13 | * @param algorithm 算法 14 | * @param password 密码(对称加密算法密钥) 15 | * @param plaintext 明文 16 | * @param publicKey 非对称加密算法(公钥) 17 | * @param metaObject {@link org.apache.ibatis.reflection.MetaObject} 18 | * @return 19 | */ 20 | @Override 21 | public String encrypt(Algorithm algorithm, String password, String publicKey, String plaintext, Object metaObject) throws Exception { 22 | // 可以判断 plaintext 是否为空加密,为空不加密直接返回 plaintext 23 | return super.encrypt(algorithm, password, publicKey, plaintext, metaObject); 24 | } 25 | 26 | /** 27 | * 解密 28 | * 29 | * @param algorithm 算法 30 | * @param password 密码(对称加密算法密钥) 31 | * @param encrypt 密文 32 | * @param privateKey 非对称加密算法(私钥) 33 | * @param metaObject {@link org.apache.ibatis.reflection.MetaObject} 34 | * @return 35 | */ 36 | @Override 37 | public String decrypt(Algorithm algorithm, String password, String privateKey, String encrypt, Object metaObject) throws Exception { 38 | // 解密密文 encrypt 39 | return super.decrypt(algorithm, password, privateKey, encrypt, metaObject); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/config/SpiceBaseMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.config; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * mybatis-plus扩展实现批量插入,只支持mysql 11 | */ 12 | public interface SpiceBaseMapper extends BaseMapper { 13 | 14 | /** 15 | * 批量插入 16 | * {@link com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn} 17 | * 18 | * @param entityList 要插入的数据 19 | * @return 成功插入的数据条数 20 | */ 21 | int insertBatchSomeColumn(@Param("list") List entityList); 22 | } 23 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/config/SpiceSqlInjector.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.config; 2 | 3 | import com.baomidou.mybatisplus.core.injector.AbstractMethod; 4 | import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; 5 | import com.baomidou.mybatisplus.core.metadata.TableInfo; 6 | import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn; 7 | import org.springframework.context.annotation.Primary; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * mybatis-plus批量插入 14 | */ 15 | @Component 16 | @Primary 17 | public class SpiceSqlInjector extends DefaultSqlInjector { 18 | 19 | @Override 20 | public List getMethodList(Class mapperClass, TableInfo tableInfo) { 21 | List methodList = super.getMethodList(mapperClass, tableInfo); 22 | methodList.add(new InsertBatchSomeColumn()); 23 | return methodList; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/config/TenantEncryptor.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.config; 2 | 3 | import mybatis.mate.encrypt.DefaultEncryptor; 4 | 5 | 6 | // 多租户自定义加解密处理器,算法继承默认算法,自己控制租户是否加解密 @Component 注解必须放在 spring 能够扫描到的目录 7 | // 控制条件一般根据上下文的租户ID自行识别处理 8 | //@Component 9 | public class TenantEncryptor extends DefaultEncryptor { 10 | 11 | @Override 12 | public boolean executeEncrypt() { 13 | // 加密 true 执行 false 不执行 14 | return true; 15 | } 16 | 17 | @Override 18 | public boolean executeDecrypt() { 19 | // 解密 true 执行 false 不执行 20 | return super.executeDecrypt(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | import mybatis.mate.annotation.Algorithm; 7 | import mybatis.mate.annotation.FieldEncrypt; 8 | 9 | @Getter 10 | @Setter 11 | @ToString 12 | public class User { 13 | private Long id; 14 | private String username; 15 | // 指定加密算法 16 | @FieldEncrypt(algorithm = Algorithm.PBEWithMD5AndDES) 17 | private String password; 18 | @FieldEncrypt 19 | private String email; 20 | @FieldEncrypt(algorithm = Algorithm.MD5_32) 21 | private String md5; 22 | @FieldEncrypt(algorithm = Algorithm.RSA) 23 | private String rsa; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/entity/UserInfo.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | import mybatis.mate.annotation.Algorithm; 7 | import mybatis.mate.annotation.FieldEncrypt; 8 | 9 | @Getter 10 | @Setter 11 | @ToString 12 | public class UserInfo { 13 | private Long id; 14 | private Long userId; 15 | @FieldEncrypt(algorithm = Algorithm.RSA) 16 | private String rsa; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/entity/dto/UserDTO.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.entity.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class UserDTO { 9 | 10 | // 文档 https://baomidou.com/pages/fd41d8/ 如果是 MP 内容方法查询可以使用以下注解,返回结果需要实体 @TableName(autoResultMap = true) 注解打开映射 11 | // @TableField(typeHandler = RSATypeHandler.class) 12 | private String email; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/entity/type/RSATypeHandler.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.entity.type; 2 | 3 | import org.apache.ibatis.type.BaseTypeHandler; 4 | import org.apache.ibatis.type.JdbcType; 5 | 6 | import java.sql.CallableStatement; 7 | import java.sql.PreparedStatement; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | 11 | public class RSATypeHandler extends BaseTypeHandler { 12 | // @Resource 13 | // private IEncryptor encryptor; 14 | // @Resource 15 | // private EncryptorProperties encryptorProperties; 16 | 17 | @Override 18 | public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { 19 | 20 | String value = parameter; 21 | // 模拟下文注释内容直接返回解密内容 22 | if (null != value) { 23 | value = "test@baomidou.com"; 24 | } 25 | // 正式环境打开一下代码执行 RSA 解密明文查询,如果数据库是密文不适用该逻辑(除非加密密文不变) 26 | // if (null != value && encryptor.executeEncrypt()) { 27 | // try { 28 | // value = encryptor.decrypt( 29 | // Algorithm.RSA, 30 | // encryptorProperties.getPassword(), 31 | // encryptorProperties.getPrivateKey(), 32 | // parameter, 33 | // null 34 | // ); 35 | // } catch (Exception e) { 36 | // throw new RuntimeException(e); 37 | // } 38 | // } 39 | ps.setString(i, value); 40 | } 41 | 42 | @Override 43 | public String getNullableResult(ResultSet rs, String columnName) throws SQLException { 44 | return rs.getString(columnName); 45 | } 46 | 47 | @Override 48 | public String getNullableResult(ResultSet rs, int i) throws SQLException { 49 | return rs.getString(i); 50 | } 51 | 52 | @Override 53 | public String getNullableResult(CallableStatement cs, int i) throws SQLException { 54 | return cs.getString(i); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/entity/vo/UserVO.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.entity.vo; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import mybatis.mate.encrypt.entity.User; 6 | import mybatis.mate.encrypt.entity.UserInfo; 7 | 8 | import java.util.List; 9 | 10 | @Getter 11 | @Setter 12 | public class UserVO extends User { 13 | private List userInfos; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/java/mybatis/mate/encrypt/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.encrypt.mapper; 2 | 3 | import mybatis.mate.encrypt.config.SpiceBaseMapper; 4 | import mybatis.mate.encrypt.entity.User; 5 | import mybatis.mate.encrypt.entity.dto.UserDTO; 6 | import mybatis.mate.encrypt.entity.vo.UserVO; 7 | import org.apache.ibatis.annotations.Mapper; 8 | import org.apache.ibatis.annotations.Param; 9 | import org.apache.ibatis.annotations.Update; 10 | 11 | import java.util.List; 12 | 13 | @Mapper 14 | public interface UserMapper extends SpiceBaseMapper { 15 | 16 | @Update("update user set password=#{u.password},email=#{u.email} where id=#{id}") 17 | Integer testUpdateById(@Param("id") Long id, @Param("u") User user); 18 | 19 | Integer insertBatchTest(@Param("userList") List userList); 20 | 21 | Integer updateBatchUserById(@Param("userList") List userList); 22 | 23 | List selectUserVOList(@Param("dto") UserDTO dto); 24 | 25 | UserVO selectUserDto(@Param("id") Long id); 26 | 27 | void testNotParams(); 28 | } 29 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | data-locations: classpath:db/data-h2.sql 12 | mode: always 13 | 14 | # Mybatis Mate 配置 15 | mybatis-mate: 16 | cert: 17 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 18 | grant: thisIsTestLicense 19 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 20 | encryptor: 21 | # 对称算法密钥,随机字符串作为密钥即可(有些算法长度有要求,注意) 22 | password: qmh9MK4KsZY8FnqkJYk8tzgc0H 23 | # 非对称加密 RSA 公钥私钥 24 | publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCEOCMScPeNaJ0DP9N9vd/fXwPGUVnuxeGPpRePXfWuX/X/Yk5IMhwEfYLXictxQk/oAqGnqtDuS/PCL/7mqL+8wFSYnWWErCSkDdT6LjyD07l9dWv+Xj1UTEjP24sEgYA92f4AZyvhsw8I/Bj6a9a30r+kVOGoEZgGMf2c2xK4CQIDAQAB 25 | privateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIQ4IxJw941onQM/0329399fA8ZRWe7F4Y+lF49d9a5f9f9iTkgyHAR9gteJy3FCT+gCoaeq0O5L88Iv/uaov7zAVJidZYSsJKQN1PouPIPTuX11a/5ePVRMSM/biwSBgD3Z/gBnK+GzDwj8GPpr1rfSv6RU4agRmAYx/ZzbErgJAgMBAAECgYBAlFK9DSQ8k14tWh1oizcvmO71DIMKluhHCvHo+pGnLAOxS0jFBoScxNkFga42kZcJ0U8337zQx5Q1ws+TxdRwHxQO889ZGQH3kOFB0ErUMTgFrTOakZhV0dMWzebkYitNcduSKZ1yfgM5ekF9k3owPIQhUNy8eXjagiLLb9/woQJBALwofOx+fuanQLC1yotFqYAx0XED9EpVPhS/G8mc4dZSNWZ548bIyq3ozP0CoHqriQo/X3NVzIJOU3rhn92fwj0CQQCz5FaeHzSqe1H4bTxzwgR5BUHttxrAPtktwfgCRgaSrZByjFldtP/dGaJmjR2Vzp848WcusJZlSlaLTfndm6W9AkEAoSxlZgctGNKn3Ta7mvU/Lmp+J7rlZU8DcK4LVXYnFXkx+OfsLvkMdE/4V7oKUUnih36lepxCJFSHubjPQf55WQJBAIUa8yxUkreCQAi9avmMGZsiVMH7tgOBfVjqKQQlpD9rxXG8f3Nitd93VD7lM3rhQ9byaBKX/vA7rQWuUK+0t1ECQDTGhLRJFZK4J7UGklTX94pknM/5rO3N/JPkFJcGilbgzkqy0s13D1K+8cR0qTn2DPW8vPoLQpVGuaATTTmMdvg= 26 | 27 | mybatis-plus: 28 | mapper-locations: classpath:/mapper/*Mapper.xml 29 | 30 | # Logger Config 31 | logging: 32 | level: 33 | mybatis.mate: debug 34 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/resources/db/data-h2.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM user; 2 | 3 | INSERT INTO user (id, username, password, email, md5, rsa) VALUES 4 | (1001, 'Jack', '6g8syWvDXx/2qYA1j57WPw==', 'test@baomidou.com', '99c5e07b4d5de9d18c350cdf64c5aa3d', 'gB2rUrFmmwlGCGaaTnVHBOays8ruCGujwdZaxP2wJYaG41QaSOcXN9ZGc/1zU3X2WuHREJVWlmqWALFZJa0FwWOMH46Bv0WpQ38x78Oms8uii23e+ZaK5Fp3cfKAxDzYzCmLO4rlPa2IjAbCKxnqV35hCGZXoa2JoRZpqsiFS/w'), 5 | (1002, 'Tom', '6g8syWvDXx/2qYA1j57WPw==', 'abc@baomidou.com', '99c5e07b4d5de9d18c350cdf64c5aa3d', 'gB2rUrFmmwlGCGaaTnVHBOays8ruCGujwdZaxP2wJYaG41QaSOcXN9ZGc/1zU3X2WuHREJVWlmqWALFZJa0FwWOMH46Bv0WpQ38x78Oms8uii23e+ZaK5Fp3cfKAxDzYzCmLO4rlPa2IjAbCKxnqV35hCGZXoa2JoRZpqsiFS/w'); 6 | 7 | DELETE FROM user_info; 8 | 9 | INSERT INTO user_info (id, user_id, rsa) VALUES 10 | (1001, 1001, 'gB2rUrFmmwlGCGaaTnVHBOays8ruCGujwdZaxP2wJYaG41QaSOcXN9ZGc/1zU3X2WuHREJVWlmqWALFZJa0FwWOMH46Bv0WpQ38x78Oms8uii23e+ZaK5Fp3cfKAxDzYzCmLO4rlPa2IjAbCKxnqV35hCGZXoa2JoRZpqsiFS/w'), 11 | (1002, 1001, 'gB2rUrFmmwlGCGaaTnVHBOays8ruCGujwdZaxP2wJYaG41QaSOcXN9ZGc/1zU3X2WuHREJVWlmqWALFZJa0FwWOMH46Bv0WpQ38x78Oms8uii23e+ZaK5Fp3cfKAxDzYzCmLO4rlPa2IjAbCKxnqV35hCGZXoa2JoRZpqsiFS/w'), 12 | (1003, 1002, 'gB2rUrFmmwlGCGaaTnVHBOays8ruCGujwdZaxP2wJYaG41QaSOcXN9ZGc/1zU3X2WuHREJVWlmqWALFZJa0FwWOMH46Bv0WpQ38x78Oms8uii23e+ZaK5Fp3cfKAxDzYzCmLO4rlPa2IjAbCKxnqV35hCGZXoa2JoRZpqsiFS/w'); 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | 3 | CREATE TABLE user 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 7 | password VARCHAR(255) NULL DEFAULT NULL COMMENT '密码', 8 | email VARCHAR(255) NULL DEFAULT NULL COMMENT '邮箱', 9 | md5 VARCHAR(255) NULL DEFAULT NULL COMMENT 'MD5不可逆', 10 | rsa VARCHAR(3000) NULL DEFAULT NULL COMMENT 'RSA', 11 | PRIMARY KEY (id) 12 | ); 13 | 14 | DROP TABLE IF EXISTS user_info; 15 | 16 | CREATE TABLE user_info 17 | ( 18 | id BIGINT(20) NOT NULL COMMENT '主键ID', 19 | user_id BIGINT(20) NOT NULL COMMENT '用户ID', 20 | rsa VARCHAR(3000) NULL DEFAULT NULL COMMENT 'RSA', 21 | PRIMARY KEY (id) 22 | ); -------------------------------------------------------------------------------- /mybatis-mate-encrypt/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | INSERT INTO user (id,username,password,email) VALUES 17 | 18 | (#{item.id},#{item.username},#{item.password},#{item.email}) 19 | 20 | 21 | 22 | 23 | 24 | UPDATE user SET password=#{item.password},email=#{item.email} WHERE id=#{item.id}; 25 | 26 | 27 | 28 | 31 | 32 | 35 | 36 | 39 | 40 | 41 | update user set username='mate' where id=1001; 42 | update user set username='plus' where id=1002; 43 | 44 | 45 | -------------------------------------------------------------------------------- /mybatis-mate-hot-reload/src/main/java/mybatis/mate/hotreload/WatchServiceTest.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.hotreload; 2 | 3 | import com.sun.nio.file.SensitivityWatchEventModifier; 4 | 5 | import java.io.IOException; 6 | import java.nio.file.*; 7 | import java.nio.file.attribute.BasicFileAttributes; 8 | 9 | public class WatchServiceTest { 10 | 11 | // https://www.cnblogs.com/zimug/p/11774958.html 12 | public static void main(String[] args) throws IOException, InterruptedException { 13 | // 构造监听服务 14 | WatchService watchService = FileSystems.getDefault().newWatchService(); 15 | Path targetPath = Paths.get( 16 | "D:\\IdeaProjects\\mybatis-mate-examples\\mybatis-mate-hot-reload\\src\\main\\resources" 17 | ).toAbsolutePath(); 18 | Files.walkFileTree(targetPath, new SimpleFileVisitor() { 19 | 20 | @Override 21 | public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs) throws IOException { 22 | //监听注册,监听实体的创建、修改、删除事件,并以高频率(每隔2秒一次,默认是10秒)监听 23 | path.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_CREATE, 24 | StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE}, 25 | SensitivityWatchEventModifier.HIGH); 26 | return FileVisitResult.CONTINUE; 27 | } 28 | }); 29 | WatchKey watchKey; 30 | do { 31 | //获取一个watch key 32 | watchKey = watchService.take(); 33 | for (WatchEvent event : watchKey.pollEvents()) { 34 | WatchEvent watchEvent = (WatchEvent) event; 35 | WatchEvent.Kind kind = watchEvent.kind(); 36 | Path watchable = ((Path) watchKey.watchable()).resolve(watchEvent.context()); 37 | 38 | // 在监听到文件夹创建的时候要把这个 path 注册到 watchService 上 39 | if (Files.isDirectory(watchable)) { 40 | if (kind == StandardWatchEventKinds.ENTRY_CREATE) { 41 | System.out.println("新建目录 = " + watchable); 42 | watchable.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, 43 | StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); 44 | } 45 | 46 | } else { 47 | if (kind == StandardWatchEventKinds.ENTRY_CREATE) { 48 | System.out.println("新建文件 = " + watchable); 49 | 50 | } else if (StandardWatchEventKinds.ENTRY_MODIFY == event.kind()) { 51 | System.out.println("修改文件 = " + watchable); 52 | 53 | } else if (StandardWatchEventKinds.ENTRY_DELETE == event.kind()) { 54 | System.out.println("删除文件 = " + watchable); 55 | } 56 | } 57 | } 58 | System.out.println("目录内容发生改变"); 59 | } while (watchKey.reset()); 60 | System.out.println("目录内容sssss发生改变"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /mybatis-mate-hot-reload/src/main/java/mybatis/mate/hotreload/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.hotreload.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class User { 9 | private Long id; 10 | private String username; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /mybatis-mate-hot-reload/src/main/java/mybatis/mate/hotreload/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.hotreload.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.hotreload.entity.User; 5 | 6 | public interface UserMapper extends BaseMapper { 7 | 8 | User selectByUsername(String username); 9 | } 10 | -------------------------------------------------------------------------------- /mybatis-mate-hot-reload/src/main/resources/m/Mm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /mybatis-mate-hot-reload/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/build.gradle: -------------------------------------------------------------------------------- 1 | description "Json数据绑定示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | 6 | testImplementation("org.springframework.boot:spring-boot-starter-test") 7 | testImplementation("junit:junit") 8 | } 9 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-jsonbind 11 | 12 | 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-maven-plugin 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/java/mybatis/mate/dict/JsonBindApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class JsonBindApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(JsonBindApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/java/mybatis/mate/dict/config/JsonBindStrategy.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.config; 2 | 3 | import mybatis.mate.databind.IJsonBindStrategy; 4 | import mybatis.mate.dict.entity.StatusEnum; 5 | import mybatis.mate.dict.entity.User; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.function.Function; 11 | 12 | @Component 13 | public class JsonBindStrategy implements IJsonBindStrategy { 14 | 15 | public interface Type { 16 | String departmentRole = "departmentRole"; 17 | 18 | } 19 | 20 | @Override 21 | public Map>> getStrategyFunctionMap() { 22 | return new HashMap>>(16) { 23 | { 24 | // 注入虚拟节点,绑定部门角色信息 25 | put(Type.departmentRole, (obj) -> new HashMap(3) {{ 26 | User user = (User) obj; 27 | put("statusText", StatusEnum.get(user.getStatus()).getDesc()); 28 | put("departmentName", "研发部"); 29 | put("roleName", "经理"); 30 | }}); 31 | } 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/java/mybatis/mate/dict/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.controller; 2 | 3 | import lombok.AllArgsConstructor; 4 | import mybatis.mate.dict.entity.User; 5 | import mybatis.mate.dict.mapper.UserMapper; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @AllArgsConstructor 11 | public class UserController { 12 | private UserMapper userMapper; 13 | 14 | // 测试访问 http://localhost:8080/info 15 | // 观察 json 结果集会动态追加非 User 类绑定的虚拟属性 16 | @GetMapping("/info") 17 | public User info() { 18 | User user = userMapper.selectById(1L); 19 | User child = new User(); 20 | child.setSex(1); 21 | child.setUsername("abc"); 22 | return user; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/java/mybatis/mate/dict/entity/StatusEnum.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.entity; 2 | 3 | public enum StatusEnum { 4 | online(0, "在线"), 5 | offline(1, "离线"), 6 | unknown(2, "未知"); 7 | 8 | private int status; 9 | private String desc; 10 | 11 | StatusEnum(final int status, final String desc) { 12 | this.status = status; 13 | this.desc = desc; 14 | } 15 | 16 | public static StatusEnum get(int status) { 17 | StatusEnum[] statusEnums = StatusEnum.values(); 18 | for (StatusEnum se : statusEnums) { 19 | if (se.status == status) { 20 | return se; 21 | } 22 | } 23 | return StatusEnum.unknown; 24 | } 25 | 26 | public String getDesc() { 27 | return desc; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/java/mybatis/mate/dict/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | import mybatis.mate.annotation.JsonBind; 7 | import mybatis.mate.dict.config.JsonBindStrategy; 8 | 9 | @Getter 10 | @Setter 11 | @ToString 12 | @JsonBind(JsonBindStrategy.Type.departmentRole) 13 | public class User { 14 | private Long id; 15 | private String username; 16 | private Integer sex; 17 | private Integer status; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/java/mybatis/mate/dict/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.dict.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.dict.entity.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface UserMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | data-locations: classpath:db/data-h2.sql 12 | mode: always 13 | 14 | # Mybatis Mate 配置 15 | mybatis-mate: 16 | cert: 17 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 18 | grant: thisIsTestLicense 19 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 20 | 21 | # Logger Config 22 | logging: 23 | level: 24 | mybatis.mate: debug 25 | -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/resources/db/data-h2.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM user; 2 | 3 | INSERT INTO user (id, username, sex, status) VALUES (1, 'Jone', 1, 1), (2, 'Jack', 0, 0), (3, 'Tom', 1, 1); -------------------------------------------------------------------------------- /mybatis-mate-jsonbind/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | 3 | CREATE TABLE user 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 7 | sex INT(2) NULL DEFAULT NULL COMMENT '性别', 8 | status INT(2) NULL DEFAULT NULL COMMENT '状态', 9 | PRIMARY KEY (id) 10 | ); -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/build.gradle: -------------------------------------------------------------------------------- 1 | description "字段脱敏 jackson 实现示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | 6 | testImplementation("org.springframework.boot:spring-boot-starter-test") 7 | testImplementation("junit:junit") 8 | } -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-sensitive-jackson 11 | 12 | 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-maven-plugin 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/java/mybatis/mate/sensitive/jackson/SensitiveJacksonApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitive.jackson; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SensitiveJacksonApplication { 8 | 9 | // 测试访问 http://localhost:8080/info ,http://localhost:8080/list 10 | public static void main(String[] args) { 11 | SpringApplication.run(SensitiveJacksonApplication.class, args); 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/java/mybatis/mate/sensitive/jackson/config/MyResponseBodyAdvice.java: -------------------------------------------------------------------------------- 1 | //package mybatis.mate.sensitive.jackson.config; 2 | // 3 | //import org.springframework.core.MethodParameter; 4 | //import org.springframework.http.MediaType; 5 | //import org.springframework.http.converter.HttpMessageConverter; 6 | //import org.springframework.http.server.ServerHttpRequest; 7 | //import org.springframework.http.server.ServerHttpResponse; 8 | //import org.springframework.web.bind.annotation.ControllerAdvice; 9 | //import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; 10 | // 11 | //@ControllerAdvice 12 | //public class MyResponseBodyAdvice implements ResponseBodyAdvice { 13 | // 14 | // @Override 15 | // public boolean supports(MethodParameter returnType, Class> converterType) { 16 | // return false; 17 | // } 18 | // 19 | // @Override 20 | // public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, 21 | // Class> selectedConverterType, 22 | // ServerHttpRequest request, ServerHttpResponse response) { 23 | // // 这里可以统一处理响应结果,如果您是这样处理的 json 转换,请注意使用 jackson 处理 24 | // return body; 25 | // } 26 | //} 27 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/java/mybatis/mate/sensitive/jackson/config/SensitiveStrategyConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitive.jackson.config; 2 | 3 | import mybatis.mate.databind.ISensitiveStrategy; 4 | import mybatis.mate.strategy.SensitiveStrategy; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class SensitiveStrategyConfig { 10 | 11 | /** 12 | * 注入脱敏策略 13 | */ 14 | @Bean 15 | public ISensitiveStrategy sensitiveStrategy() { 16 | // 自定义 testStrategy 类型脱敏处理 17 | return new SensitiveStrategy().addStrategy("testStrategy", t -> t + "***test***"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/java/mybatis/mate/sensitive/jackson/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitive.jackson.controller; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import mybatis.mate.databind.ISensitiveStrategy; 5 | import mybatis.mate.databind.RequestDataTransfer; 6 | import mybatis.mate.sensitive.jackson.entity.User; 7 | import mybatis.mate.sensitive.jackson.mapper.UserMapper; 8 | import mybatis.mate.strategy.SensitiveType; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | import java.util.Objects; 17 | 18 | @RestController 19 | public class UserController { 20 | @Autowired 21 | private UserMapper userMapper; 22 | @Autowired 23 | private ISensitiveStrategy sensitiveStrategy; 24 | 25 | // 测试访问 http://localhost:8080/info 26 | @GetMapping("/info") 27 | public User info() { 28 | return userMapper.selectById(1L); 29 | } 30 | 31 | // 测试返回 map 访问 http://localhost:8080/map 32 | @GetMapping("/map") 33 | public Map map() { 34 | // 测试嵌套对象脱敏 35 | Map userMap = new HashMap<>(); 36 | userMap.put("user", userMapper.selectById(1L)); 37 | userMap.put("test", 123); 38 | userMap.put("userMap", new HashMap() {{ 39 | put("user2", userMapper.selectById(2L)); 40 | put("test2", "hi china"); 41 | }}); 42 | // 手动调用策略脱敏 43 | userMap.put("mobile", sensitiveStrategy.getStrategyFunctionMap() 44 | .get(SensitiveType.mobile).apply("15315388888")); 45 | return userMap; 46 | } 47 | 48 | // 测试访问 http://localhost:8080/list 49 | // 全部不脱敏 http://localhost:8080/list?skip=1 50 | // 指定属性不脱敏 http://localhost:8080/list?skip=2 51 | @GetMapping("/list") 52 | public List list(HttpServletRequest request) { 53 | String skip = request.getParameter("skip"); 54 | if (Objects.equals("1", skip)) { 55 | // 跳过脱密处理 56 | RequestDataTransfer.skipSensitive(); 57 | } else if (null != skip) { 58 | // 忽略 username 及 email 属性 59 | RequestDataTransfer.skipSensitive("username;email"); 60 | } 61 | return userMapper.selectList(null); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/java/mybatis/mate/sensitive/jackson/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitive.jackson.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import mybatis.mate.annotation.FieldSensitive; 6 | import mybatis.mate.sensitive.jackson.config.SensitiveStrategyConfig; 7 | import mybatis.mate.strategy.SensitiveType; 8 | 9 | @Getter 10 | @Setter 11 | public class User { 12 | private Long id; 13 | /** 14 | * 这里是一个自定义的策略 {@link SensitiveStrategyConfig} 初始化注入 15 | */ 16 | @FieldSensitive("testStrategy") 17 | private String username; 18 | /** 19 | * 默认支持策略 {@link SensitiveType } 20 | */ 21 | @FieldSensitive(SensitiveType.mobile) 22 | private String mobile; 23 | @FieldSensitive(SensitiveType.email) 24 | private String email; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/java/mybatis/mate/sensitive/jackson/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitive.jackson.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.sensitive.jackson.entity.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface UserMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | data-locations: classpath:db/data-h2.sql 12 | mode: always 13 | 14 | # Mybatis Mate 配置 15 | mybatis-mate: 16 | cert: 17 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 18 | grant: thisIsTestLicense 19 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 20 | 21 | # Logger Config 22 | logging: 23 | level: 24 | mybatis.mate: debug 25 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/resources/db/data-h2.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM user; 2 | 3 | INSERT INTO user (id, username, mobile, email) VALUES 4 | (1, 'Jone', '15315388881', 'test1@baomidou.com'), 5 | (2, 'Jack', '15315388882', 'test2@baomidou.com'), 6 | (3, 'Tom', '15315388883', 'test3@baomidou.com'); 7 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-jackson/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | 3 | CREATE TABLE user 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 7 | mobile VARCHAR(11) NULL DEFAULT NULL COMMENT '手机号', 8 | email VARCHAR(255) NULL DEFAULT NULL COMMENT '邮箱', 9 | PRIMARY KEY (id) 10 | ); -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/build.gradle: -------------------------------------------------------------------------------- 1 | description "请求参数 敏感词 过滤示例" 2 | 3 | dependencies { 4 | implementation("com.h2database:h2") 5 | // AC 算法依赖 6 | implementation("org.ahocorasick:ahocorasick:0.6.3") 7 | 8 | testImplementation("org.springframework.boot:spring-boot-starter-test") 9 | testImplementation("junit:junit") 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-sensitive-words 11 | 12 | 13 | 14 | org.ahocorasick 15 | ahocorasick 16 | 0.6.3 17 | 18 | 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-maven-plugin 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/SensitiveWordsApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SensitiveWordsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SensitiveWordsApplication.class, args); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/config/ParamsConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.config; 2 | 3 | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; 4 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import lombok.AllArgsConstructor; 7 | import mybatis.mate.params.IParamsProcessor; 8 | import mybatis.mate.params.SensitiveWordsProcessor; 9 | import mybatis.mate.sensitivewords.entity.SensitiveWords; 10 | import mybatis.mate.sensitivewords.mapper.SensitiveWordsMapper; 11 | import org.ahocorasick.trie.Emit; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | import java.util.Collection; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | @Configuration 20 | @AllArgsConstructor 21 | public class ParamsConfig { 22 | private SensitiveWordsMapper sensitiveWordsMapper; 23 | 24 | @Bean 25 | public IParamsProcessor paramsProcessor() { 26 | return new SensitiveWordsProcessor() { 27 | 28 | /** 29 | // 可以指定你需要拦截处理的请求地址,默认 /* 所有请求 30 | @Override public Collection getUrlPatterns() { 31 | return super.getUrlPatterns(); 32 | } 33 | */ 34 | 35 | @Override 36 | public List loadSensitiveWords() { 37 | // 这里的敏感词可以从数据库中读取,也可以本文方式获取,加载只会执行一次 38 | return sensitiveWordsMapper.selectList(Wrappers.lambdaQuery().select(SensitiveWords::getWord)) 39 | .stream().map(t -> t.getWord()).collect(Collectors.toList()); 40 | } 41 | 42 | @Override 43 | public String handle(String fieldName, String fieldValue, Collection emits) { 44 | if (CollectionUtils.isNotEmpty(emits)) { 45 | try { 46 | // 这里可以过滤直接删除敏感词,也可以返回错误,提示界面删除敏感词 47 | System.err.println("发现敏感词(" + fieldName + " = " + fieldValue + ")" + 48 | "存在敏感词:" + toJson(emits)); 49 | String fv = fieldValue; 50 | for (Emit emit : emits) { 51 | fv = fv.replaceAll(emit.getKeyword(), ""); 52 | } 53 | return fv; 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | return fieldValue; 59 | } 60 | }; 61 | } 62 | 63 | // @Bean 64 | // public SensitiveRequestBodyAdvice sensitiveRequestBodyAdvice(IParamsProcessor paramsProcessor) { 65 | // return new SensitiveRequestBodyAdvice(paramsProcessor); 66 | // } 67 | 68 | // @Bean 69 | // @Primary 70 | // public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(IParamsProcessor paramsProcessor) { 71 | // SimpleModule module = new SimpleModule(); 72 | // // 注入 json 参数反序列化器 ParamsJsonDeserializer 73 | // module.addDeserializer(String.class, new ParamsJsonDeserializer(paramsProcessor)); 74 | // // 注册解析器 75 | // ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build(); 76 | // objectMapper.registerModule(module); 77 | // return new MappingJackson2HttpMessageConverter(objectMapper); 78 | // } 79 | 80 | private static ObjectMapper OBJECT_MAPPER; 81 | 82 | public static String toJson(Object object) throws Exception { 83 | if (null == OBJECT_MAPPER) { 84 | OBJECT_MAPPER = new ObjectMapper(); 85 | } 86 | return OBJECT_MAPPER.writeValueAsString(object); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/config/SensitiveRequestBodyAdvice.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.config; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import mybatis.mate.params.IParamsProcessor; 5 | import org.springframework.core.MethodParameter; 6 | import org.springframework.http.HttpInputMessage; 7 | import org.springframework.http.converter.HttpMessageConverter; 8 | import org.springframework.http.converter.json.MappingJacksonInputMessage; 9 | import org.springframework.util.StreamUtils; 10 | import org.springframework.web.bind.annotation.RestControllerAdvice; 11 | import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter; 12 | 13 | import java.io.ByteArrayInputStream; 14 | import java.io.IOException; 15 | import java.lang.reflect.Type; 16 | import java.nio.charset.StandardCharsets; 17 | 18 | /** 19 | * 接口请求敏感词处理切点 20 | */ 21 | @Slf4j 22 | @RestControllerAdvice 23 | public class SensitiveRequestBodyAdvice extends RequestBodyAdviceAdapter { 24 | private final IParamsProcessor paramsProcessor; 25 | 26 | public SensitiveRequestBodyAdvice(IParamsProcessor paramsProcessor) { 27 | this.paramsProcessor = paramsProcessor; 28 | } 29 | 30 | @Override 31 | public boolean supports(MethodParameter methodParameter, Type targetType, 32 | Class> converterType) { 33 | Class clazz; 34 | // if (targetType instanceof ParameterizedTypeImpl) { 35 | // clazz = ((ParameterizedTypeImpl) targetType).getRawType(); 36 | // } else { 37 | clazz = (Class) targetType; 38 | // } 39 | return Sensitived.class.isAssignableFrom(clazz); 40 | } 41 | 42 | @Override 43 | public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, 44 | Class> converterType) { 45 | try { 46 | String content = StreamUtils.copyToString(inputMessage.getBody(), StandardCharsets.UTF_8); 47 | ByteArrayInputStream inputStream = new ByteArrayInputStream(paramsProcessor.execute("json", 48 | content).getBytes(StandardCharsets.UTF_8)); 49 | return new MappingJacksonInputMessage(inputStream, inputMessage.getHeaders()); 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | return inputMessage; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/config/Sensitived.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.config; 2 | 3 | /** 4 | * 敏感词接口 5 | */ 6 | public interface Sensitived { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/controller/ArticleController.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.controller; 2 | 3 | import mybatis.mate.params.SensitiveWordsProcessor; 4 | import mybatis.mate.sensitivewords.config.ParamsConfig; 5 | import mybatis.mate.sensitivewords.entity.Article; 6 | import mybatis.mate.sensitivewords.entity.ArticleNoneSensitive; 7 | import mybatis.mate.sensitivewords.entity.SensitiveWords; 8 | import mybatis.mate.sensitivewords.mapper.SensitiveWordsMapper; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.PostMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * 演示文章敏感词过滤 17 | */ 18 | @RestController 19 | public class ArticleController { 20 | @Autowired 21 | private SensitiveWordsMapper sensitiveWordsMapper; 22 | 23 | // 测试访问下面地址观察请求地址、界面返回数据及控制台( 普通参数 ) 24 | // 无敏感词 http://localhost:8080/info?content=tom&see=1&age=18 25 | // 英文敏感词 http://localhost:8080/info?content=my%20content%20is%20tomcat&see=1&age=18 26 | // 汉字敏感词 http://localhost:8080/info?content=%E7%8E%8B%E5%AE%89%E7%9F%B3%E5%94%90%E5%AE%8B%E5%85%AB%E5%A4%A7%E5%AE%B6&see=1 27 | // 多个敏感词 http://localhost:8080/info?content=%E7%8E%8B%E5%AE%89%E7%9F%B3%E6%9C%89%E4%B8%80%E5%8F%AA%E7%8C%ABtomcat%E6%B1%A4%E5%A7%86%E5%87%AF%E7%89%B9&see=1&size=6 28 | // 插入一个字变成非敏感词 http://localhost:8080/info?content=%E7%8E%8B%E7%8C%AB%E5%AE%89%E7%9F%B3%E6%9C%89%E4%B8%80%E5%8F%AA%E7%8C%ABtomcat%E6%B1%A4%E5%A7%86%E5%87%AF%E7%89%B9&see=1&size=6 29 | @GetMapping("/info") 30 | public String info(Article article) throws Exception { 31 | return ParamsConfig.toJson(article); 32 | } 33 | 34 | 35 | // 添加一个敏感词然后再去观察是否生效 http://localhost:8080/add 36 | // 观察【猫】这个词被过滤了 http://localhost:8080/add?content=%E7%8E%8B%E5%AE%89%E7%9F%B3%E6%9C%89%E4%B8%80%E5%8F%AA%E7%8C%ABtomcat%E6%B1%A4%E5%A7%86%E5%87%AF%E7%89%B9&see=1&size=6 37 | // 嵌套敏感词处理 http://localhost:8080/info?content=%E7%8E%8B%E7%8C%AB%E5%AE%89%E7%9F%B3%E6%9C%89%E4%B8%80%E5%8F%AA%E7%8C%ABtomcat%E6%B1%A4%E5%A7%86%E5%87%AF%E7%89%B9&see=1&size=6 38 | // 多层嵌套敏感词 http://localhost:8080/info?content=%E7%8E%8B%E7%8E%8B%E7%8C%AB%E5%AE%89%E7%9F%B3%E5%AE%89%E7%9F%B3%E6%9C%89%E4%B8%80%E5%8F%AA%E7%8C%ABtomcat%E6%B1%A4%E5%A7%86%E5%87%AF%E7%89%B9&see=1&size=6 39 | @GetMapping("/add") 40 | public String add() throws Exception { 41 | Long id = 3L; 42 | if (null == sensitiveWordsMapper.selectById(id)) { 43 | System.err.println("插入一个敏感词:" + sensitiveWordsMapper.insert(new SensitiveWords(id, "猫"))); 44 | // 插入一个敏感词,刷新算法引擎敏感词 45 | SensitiveWordsProcessor.reloadSensitiveWords(); 46 | } 47 | return "ok"; 48 | } 49 | 50 | // 测试访问下面地址观察控制台( 请求json参数 ) 51 | // idea 执行 resources 目录 TestJson.http 文件测试 52 | @PostMapping("/json") 53 | public String json(@RequestBody Article article) throws Exception { 54 | return ParamsConfig.toJson(article); 55 | } 56 | 57 | // 这里未实现 Sensitived 接口 SensitiveRequestBodyAdvice 不调用脱敏 58 | @PostMapping("/test") 59 | public String test(@RequestBody ArticleNoneSensitive article) throws Exception { 60 | return ParamsConfig.toJson(article); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/entity/Article.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import mybatis.mate.sensitivewords.config.Sensitived; 6 | 7 | @Getter 8 | @Setter 9 | public class Article implements Sensitived { 10 | // 内容 11 | private String content; 12 | // 阅读数 13 | private Integer see; 14 | // 字数 15 | private Long size; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/entity/ArticleNoneSensitive.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class ArticleNoneSensitive { 9 | private String content; 10 | private Integer see; 11 | private Long size; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/entity/SensitiveWords.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class SensitiveWords { 13 | private Long id; 14 | private String word; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/java/mybatis/mate/sensitivewords/mapper/SensitiveWordsMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sensitivewords.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.sensitivewords.entity.SensitiveWords; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface SensitiveWordsMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/resources/TestJson.http: -------------------------------------------------------------------------------- 1 | 2 | POST http://localhost:8080/json 3 | Content-Type: application/json 4 | 5 | { 6 | "content": "王安石有一只猫tomcat汤姆凯特", 7 | "see": 1, 8 | "size": 6 9 | } 10 | 11 | ### 12 | 13 | POST http://localhost:8080/json 14 | Content-Type: application/json 15 | 16 | { 17 | "content": "没有敏感词", 18 | "see": 1, 19 | "size": 6 20 | } 21 | 22 | ### 23 | 24 | POST http://localhost:8080/test 25 | Content-Type: application/json 26 | 27 | { 28 | "content": "一只猫tomcat汤姆凯特,不处理敏感词", 29 | "see": 1, 30 | "size": 2 31 | } 32 | 33 | ### 34 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # DataSource Config 2 | spring: 3 | datasource: 4 | driver-class-name: org.h2.Driver 5 | url: jdbc:h2:mem:test 6 | username: root 7 | password: test 8 | sql: 9 | init: 10 | schema-locations: classpath:db/schema-h2.sql 11 | data-locations: classpath:db/data-h2.sql 12 | mode: always 13 | 14 | # Mybatis Mate 配置 15 | mybatis-mate: 16 | cert: 17 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 18 | grant: thisIsTestLicense 19 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 20 | 21 | # Logger Config 22 | logging: 23 | level: 24 | mybatis.mate: debug 25 | -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/resources/db/data-h2.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM sensitive_words; 2 | 3 | INSERT INTO sensitive_words (id, word) VALUES (1, '王安石'), (2, 'tomcat'); -------------------------------------------------------------------------------- /mybatis-mate-sensitive-words/src/main/resources/db/schema-h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS sensitive_words; 2 | 3 | CREATE TABLE sensitive_words 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | word VARCHAR(30) NULL DEFAULT NULL COMMENT '敏感词', 7 | PRIMARY KEY (id) 8 | ); -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/build.gradle: -------------------------------------------------------------------------------- 1 | description "动态数据源加载卸载示例" 2 | 3 | dependencies { 4 | implementation("org.springframework.boot:spring-boot-starter-actuator") 5 | implementation("mysql:mysql-connector-java") 6 | 7 | testImplementation("org.springframework.boot:spring-boot-starter-test") 8 | testImplementation("junit:junit") 9 | } 10 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-sharding-dynamic 11 | 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-actuator 16 | 17 | 18 | mysql 19 | mysql-connector-java 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-maven-plugin 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/java/mybatis/mate/sharding/dynamic/ShardingDynamicApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.dynamic; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ShardingDynamicApplication { 8 | 9 | // 本测试在 mybatis-mate-sharding 基础上测试,查看 UserController 类注释说明 10 | public static void main(String[] args) { 11 | SpringApplication.run(ShardingDynamicApplication.class, args); 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/java/mybatis/mate/sharding/dynamic/config/MyDatabaseIdProvider.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.dynamic.config; 2 | 3 | import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; 4 | import org.apache.ibatis.mapping.DatabaseIdProvider; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.sql.DataSource; 8 | import java.sql.SQLException; 9 | 10 | @Component 11 | public class MyDatabaseIdProvider implements DatabaseIdProvider { 12 | 13 | @Override 14 | public String getDatabaseId(DataSource dataSource) throws SQLException { 15 | String jdbcUrl = dataSource.getConnection().getMetaData().getURL(); 16 | return JdbcUtils.getDbType(jdbcUrl).getDb(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/java/mybatis/mate/sharding/dynamic/config/MyShardingProcessor.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.dynamic.config; 2 | 3 | import mybatis.mate.sharding.IShardingProcessor; 4 | import org.apache.ibatis.mapping.MappedStatement; 5 | import org.apache.ibatis.plugin.Invocation; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class MyShardingProcessor implements IShardingProcessor { 10 | 11 | /** 12 | * 切换数据源,返回 false 使用默认数据源切换规则 13 | * 14 | * @param invocation {@link Invocation} 15 | * @param mappedStatement {@link MappedStatement} 16 | * @param datasourceKey 数据源关键字 17 | * @return true 成功 false 失败 18 | */ 19 | @Override 20 | public boolean changeDatasource(Invocation invocation, MappedStatement mappedStatement, 21 | String datasourceKey) { 22 | System.err.println(" 执行方法:" + mappedStatement.getId()); 23 | System.err.println(" datasourceKey = " + datasourceKey); 24 | // 如果想自定义控制切换那个数据源可以在此方法中处理 25 | // ShardingKey.change(数据源Key) 26 | // 返回 true 则按照你的切换方案执行 false 默认规则切换 @Sharding 注解才有效 27 | // datasourceKey = null 时候 mate 底层依然会使用默认数据源 28 | return true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/java/mybatis/mate/sharding/dynamic/config/ShardingConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.dynamic.config; 2 | 3 | import mybatis.mate.config.DataSourceProperty; 4 | import mybatis.mate.config.ShardingProperties; 5 | import mybatis.mate.provider.HikariDataSourceProvider; 6 | import mybatis.mate.provider.IDataSourceProvider; 7 | import mybatis.mate.sharding.ShardingDatasource; 8 | import mybatis.mate.strategy.IShardingStrategy; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.context.annotation.Primary; 13 | 14 | import javax.sql.DataSource; 15 | import java.sql.SQLException; 16 | import java.util.Arrays; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.concurrent.ConcurrentHashMap; 21 | 22 | @Configuration 23 | public class ShardingConfig { 24 | @Autowired(required = false) 25 | private IShardingStrategy shardingStrategy; 26 | 27 | @Bean 28 | public IDataSourceProvider dataSourceProvider() { 29 | return new HikariDataSourceProvider(); 30 | } 31 | 32 | /** 33 | * 这里是代码初始化数据源方式 34 | */ 35 | // @Primary 36 | // @Bean(name = "dataSource") 37 | public ShardingDatasource shardingDatasource(IDataSourceProvider dataSourceProvider, ShardingProperties shardingProperties) { 38 | shardingProperties.setPrimary("mysql"); 39 | DataSourceProperty mysqlT1 = new DataSourceProperty(); 40 | mysqlT1.setKey("t1"); 41 | mysqlT1.setDriverClassName("com.mysql.cj.jdbc.Driver"); 42 | mysqlT1.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"); 43 | mysqlT1.setUsername("root"); 44 | mysqlT1.setSchema("test"); 45 | shardingProperties.setDatasource(new HashMap<>(16) {{ 46 | put("mysql", Arrays.asList(mysqlT1)); 47 | }}); 48 | Map dataSources = new HashMap<>(16); 49 | Map dataSourceProperties = new ConcurrentHashMap<>(16); 50 | shardingProperties.getDatasource().forEach((k, v) -> v.forEach(d -> { 51 | try { 52 | String datasourceKey = k + d.getKey(); 53 | dataSources.put(datasourceKey, dataSourceProvider.createDataSource(k, d)); 54 | dataSourceProperties.put(datasourceKey, d); 55 | } catch (SQLException e) { 56 | e.printStackTrace(); 57 | } 58 | })); 59 | if (null != shardingStrategy) { 60 | shardingProperties.setShardingStrategy(shardingStrategy); 61 | } 62 | return new ShardingDatasource(dataSourceProvider, dataSources, dataSourceProperties, shardingProperties); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/java/mybatis/mate/sharding/dynamic/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.dynamic.controller; 2 | 3 | import mybatis.mate.config.DataSourceProperty; 4 | import mybatis.mate.sharding.ShardingDatasource; 5 | import mybatis.mate.sharding.dynamic.entity.User; 6 | import mybatis.mate.sharding.dynamic.mapper.UserMapper; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import java.util.List; 12 | 13 | @RestController 14 | public class UserController { 15 | @Autowired 16 | private ShardingDatasource shardingDatasource; 17 | @Autowired 18 | private UserMapper mapper; 19 | 20 | // 测试访问 http://localhost:8080/test 观察返回结果集 21 | // 切换数据源 http://localhost:8080/test?db=test2 22 | @GetMapping("/test") 23 | public List test(String db) throws Exception { 24 | // 这里始终使用默认数据源切换规则,更多细节可以查看 MyShardingProcessor 处理器打印信息 25 | System.err.println("~~~ count = " + mapper.selectCount(null)); 26 | if ("test2".equals(db)) { 27 | // 切换到指定数据源,如果数据源之前不存在会装载配置源 28 | // 数据源的装载可以放到初始化或者添加新数据源的逻辑里面执行 29 | shardingDatasource.change(db, key -> DataSourceProperty.of( 30 | "com.mysql.cj.jdbc.Driver", 31 | "jdbc:mysql://localhost:3306/" + db + "?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC", 32 | "root", 33 | null 34 | )); 35 | // 卸载数据源 36 | // shardingDatasource.removeDataSource(db); 37 | } 38 | // 请求地址 db=test2 这里会切换到数据源 test2 界面显示数据会发生变好 39 | return mapper.selectList(null); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/java/mybatis/mate/sharding/dynamic/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.dynamic.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | /** 8 | * 9 | */ 10 | @Getter 11 | @Setter 12 | @ToString 13 | public class User { 14 | private Long id; 15 | private String username; 16 | private String password; 17 | private Integer sex; 18 | private String email; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/java/mybatis/mate/sharding/dynamic/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.dynamic.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.sharding.dynamic.entity.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface UserMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Mybatis Mate 配置 2 | mybatis-mate: 3 | cert: 4 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 5 | grant: thisIsTestLicense 6 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 7 | # 采用代码初始化,这里注释即可,需要健康检测启动的时候需要配置 yml 初始化数据源 8 | sharding: 9 | # health: true # 健康检测 10 | primary: mysql # 默认选择数据源,该项配置必须有否则无法加载启动 11 | datasource: 12 | mysql: 13 | - key: t1 14 | driver-class-name: com.mysql.cj.jdbc.Driver 15 | url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 16 | username: root 17 | schema: test 18 | 19 | # 允许bean定义重写 20 | spring: 21 | main: 22 | allow-bean-definition-overriding: true 23 | 24 | # 配置健康检查 25 | management: 26 | endpoint: 27 | health: 28 | show-details: always 29 | health: 30 | defaults: 31 | enabled: false 32 | db: 33 | enabled: true 34 | 35 | # Logger Config 36 | logging: 37 | level: 38 | mybatis.mate: debug 39 | org.apache: debug 40 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-dynamic/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/build.gradle: -------------------------------------------------------------------------------- 1 | description "数据库分库分表多数动态据源示例" 2 | 3 | dependencies { 4 | implementation("org.springframework.boot:spring-boot-starter-actuator") 5 | implementation("org.postgresql:postgresql") 6 | implementation("mysql:mysql-connector-java") 7 | // spring boot 推荐 jta atomikos 分布式事务解决方案 8 | implementation("org.springframework.boot:spring-boot-starter-jta-atomikos:2.7.7") 9 | 10 | testImplementation("org.springframework.boot:spring-boot-starter-test") 11 | testImplementation("junit:junit") 12 | } 13 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-sharding-jta-atomikos 11 | 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-actuator 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-jta-atomikos 20 | 2.7.7 21 | 22 | 23 | org.postgresql 24 | postgresql 25 | 26 | 27 | mysql 28 | mysql-connector-java 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-maven-plugin 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/ShardingJtaAtomikosApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 6 | import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration; 7 | import org.springframework.transaction.annotation.EnableTransactionManagement; 8 | 9 | @SpringBootApplication 10 | // 注意事务管理器要打开 11 | @EnableTransactionManagement 12 | public class ShardingJtaAtomikosApplication { 13 | 14 | // 测试查看 TestController 方法注释 15 | public static void main(String[] args) { 16 | SpringApplication.run(ShardingJtaAtomikosApplication.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/config/Db1.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.config; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.IDdl; 4 | import lombok.AllArgsConstructor; 5 | import mybatis.mate.sharding.ShardingDatasource; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.sql.DataSource; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.function.Consumer; 12 | 13 | @Component 14 | @AllArgsConstructor 15 | public class Db1 implements IDdl { 16 | private ShardingDatasource shardingDatasource; 17 | 18 | @Override 19 | public void runScript(Consumer consumer) { 20 | consumer.accept(shardingDatasource.getDataSource("testt1")); 21 | } 22 | 23 | /** 24 | * 执行 SQL 脚本方式 25 | */ 26 | @Override 27 | public List getSqlFiles() { 28 | return Arrays.asList("db/order-db1.sql"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/config/Db2.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.config; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.IDdl; 4 | import lombok.AllArgsConstructor; 5 | import mybatis.mate.sharding.ShardingDatasource; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.sql.DataSource; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.function.Consumer; 12 | 13 | @Component 14 | @AllArgsConstructor 15 | public class Db2 implements IDdl { 16 | private ShardingDatasource shardingDatasource; 17 | 18 | @Override 19 | public void runScript(Consumer consumer) { 20 | consumer.accept(shardingDatasource.getDataSource("test2t1")); 21 | } 22 | 23 | /** 24 | * 执行 SQL 脚本方式 25 | */ 26 | @Override 27 | public List getSqlFiles() { 28 | return Arrays.asList("db/sku-db2.sql"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/config/Db3.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.config; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.IDdl; 4 | import com.baomidou.mybatisplus.extension.ddl.history.IDdlGenerator; 5 | import com.baomidou.mybatisplus.extension.ddl.history.PostgreDdlGenerator; 6 | import lombok.AllArgsConstructor; 7 | import mybatis.mate.sharding.ShardingDatasource; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.sql.DataSource; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | import java.util.function.Consumer; 14 | 15 | @Component 16 | @AllArgsConstructor 17 | public class Db3 implements IDdl { 18 | private ShardingDatasource shardingDatasource; 19 | 20 | @Override 21 | public void runScript(Consumer consumer) { 22 | consumer.accept(shardingDatasource.getDataSource("test3t1")); 23 | } 24 | 25 | /** 26 | * 执行 SQL 脚本方式 27 | */ 28 | @Override 29 | public List getSqlFiles() { 30 | return Arrays.asList("db/log-db3.sql"); 31 | } 32 | 33 | /** 34 | * 该方法也可以不指定 ddl 生成器默认自动识别 35 | */ 36 | @Override 37 | public IDdlGenerator getDdlGenerator() { 38 | // 指定数据库 ddl 创建处理器 39 | return PostgreDdlGenerator.newInstance(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/config/ShardingConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.config; 2 | 3 | import com.mysql.cj.jdbc.MysqlXADataSource; 4 | import mybatis.mate.config.DataSourceProperty; 5 | import mybatis.mate.provider.AtomikosDataSourceProvider; 6 | import mybatis.mate.provider.IDataSourceProvider; 7 | import mybatis.mate.sharding.IShardingProcessor; 8 | import org.apache.ibatis.mapping.MappedStatement; 9 | import org.postgresql.xa.PGXADataSource; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | import javax.sql.XADataSource; 14 | import java.sql.SQLException; 15 | 16 | @Configuration 17 | public class ShardingConfig { 18 | 19 | /** 20 | * 可注释 @bean 注解测试无效事务 21 | */ 22 | @Bean 23 | public IDataSourceProvider dataSourceProvider() { 24 | // jta atomikos 分布式事务 25 | return new AtomikosDataSourceProvider() { 26 | 27 | /** 28 | * 创建 XADataSource 数据源 29 | * 30 | * @param group 数据库分组 31 | * @param dataSourceProperty 数据源配置 32 | * @return 33 | */ 34 | @Override 35 | public XADataSource createXADataSource(String group, DataSourceProperty dataSourceProperty) throws SQLException { 36 | // 根据数据库类型可以创建指定 XA 数据源 37 | final String driverClassName = dataSourceProperty.getDriverClassName(); 38 | System.out.println("数据库类型:" + driverClassName); 39 | if (driverClassName.contains("postgresql")) { 40 | // postgresql xa 41 | PGXADataSource pgxaDataSource = new PGXADataSource(); 42 | pgxaDataSource.setUrl(dataSourceProperty.getUrl()); 43 | pgxaDataSource.setUser(dataSourceProperty.getUsername()); 44 | pgxaDataSource.setPassword(dataSourceProperty.getPassword()); 45 | return pgxaDataSource; 46 | } 47 | 48 | // mysql xa 49 | MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource(); 50 | mysqlXaDataSource.setUrl(dataSourceProperty.getUrl()); 51 | mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true); 52 | mysqlXaDataSource.setUser(dataSourceProperty.getUsername()); 53 | mysqlXaDataSource.setPassword(dataSourceProperty.getPassword()); 54 | mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true); 55 | return mysqlXaDataSource; 56 | } 57 | }; 58 | } 59 | 60 | @Bean 61 | public IShardingProcessor shardingProcessor() { 62 | /** 63 | * 切换数据源,返回 false 使用默认数据源切换规则 64 | * 65 | * @param args 执行参数 66 | * @param mappedStatement {@link MappedStatement} 67 | * @param datasourceKey 数据源关键字 68 | * @return true 手动切换成功,底层不会处理 false 交给底层随机自行切换 69 | */ 70 | // 改变系统切换策略可以实现 IShardingStrategy 策略 71 | return (args, mappedStatement, datasourceKey) -> false; 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.controller; 2 | 3 | import lombok.AllArgsConstructor; 4 | import mybatis.mate.sharding.jta.atomikos.service.BuyService; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @AllArgsConstructor 10 | public class TestController { 11 | private BuyService buyService; 12 | 13 | // 数据库 test 表 t_order 在事务一致情况无法插入数据,能够插入说明多数据源事务无效 14 | // 测试访问 http://localhost:8080/test 15 | // 制造事务回滚 http://localhost:8080/test?error=true 也可通过修改表结构制造错误 16 | // 注释 ShardingConfig 注入 dataSourceProvider 可测试事务无效情况 17 | @GetMapping("/test") 18 | public String test(Boolean error) { 19 | return buyService.buy(null != error && error); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/entity/Log.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * 日志表 8 | */ 9 | @Getter 10 | @Setter 11 | public class Log { 12 | // 注解 ID 13 | private Long id; 14 | // 日志内容 15 | private String content; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/entity/Order.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * 测试订单 11 | */ 12 | @Getter 13 | @Setter 14 | @TableName("t_order") 15 | public class Order { 16 | // 主键 ID 17 | private Long id; 18 | // SKU ID 19 | private Long skuId; 20 | // 数量 21 | private Integer quantity; 22 | // 价格 23 | private BigDecimal price; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/entity/Sku.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | /** 8 | * SKU 表 9 | */ 10 | @Getter 11 | @Setter 12 | public class Sku { 13 | // 主键 ID 14 | private Long id; 15 | // 商品 16 | private String product; 17 | // 颜色 18 | private String color; 19 | // 库存 20 | @TableField(update = "stock-#{et.stock}") // 注入自减指定值策略 21 | private Integer stock; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/mapper/LogMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.annotation.Sharding; 5 | import mybatis.mate.sharding.jta.atomikos.entity.Log; 6 | import org.apache.ibatis.annotations.Mapper; 7 | 8 | @Mapper 9 | @Sharding("test3") 10 | public interface LogMapper extends BaseMapper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.sharding.jta.atomikos.entity.Order; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | @Mapper 8 | public interface OrderMapper extends BaseMapper { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/mapper/SkuMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.annotation.Sharding; 5 | import mybatis.mate.sharding.jta.atomikos.entity.Sku; 6 | import org.apache.ibatis.annotations.Mapper; 7 | 8 | @Mapper 9 | @Sharding("test2") 10 | public interface SkuMapper extends BaseMapper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/service/BuyService.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.service; 2 | 3 | import lombok.AllArgsConstructor; 4 | import org.springframework.stereotype.Service; 5 | import org.springframework.transaction.annotation.Transactional; 6 | 7 | @Service 8 | @AllArgsConstructor 9 | public class BuyService { 10 | public OrderService orderService; 11 | public SkuService skuService; 12 | public LogService logService; 13 | 14 | @Transactional(rollbackFor = Exception.class) 15 | public String buy(boolean error) { 16 | final Long skuId = 3L; 17 | final Integer quantity = 1; 18 | 19 | // 数据库 test 创建订单 20 | orderService.createOrder(skuId, quantity); 21 | 22 | // 数据库 test2 减掉库存 23 | skuService.reduceStock(skuId, quantity, error); 24 | 25 | // 数据库 test3 记录日志 26 | logService.save("订单 123 下单成功"); 27 | return "ok"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/service/LogService.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.service; 2 | 3 | import lombok.AllArgsConstructor; 4 | import mybatis.mate.sharding.jta.atomikos.entity.Log; 5 | import mybatis.mate.sharding.jta.atomikos.mapper.LogMapper; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | @AllArgsConstructor 10 | public class LogService { 11 | private LogMapper logMapper; 12 | 13 | /** 14 | * 减少库存 15 | * 16 | * !!!执行遇到如下错误!!! 17 | * 【 18 | * Caused by: org.postgresql.util.PSQLException: 错误: 禁用已准备好的事务 19 | * 建议:将max_prepared_transactions设置为一个非零值 20 | * 】 21 | * 原因:默认情况下,PostgreSQL并不开启两阶段提交,可以通过在postgresql.conf文件中 22 | * 设置 max_prepared_transactions 配置项开启PostgreSQL的两阶段提交。 23 | */ 24 | public void save(String content) { 25 | Log log = new Log(); 26 | log.setContent(content); 27 | logMapper.insert(log); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.service; 2 | 3 | import lombok.AllArgsConstructor; 4 | import mybatis.mate.sharding.jta.atomikos.entity.Order; 5 | import mybatis.mate.sharding.jta.atomikos.mapper.OrderMapper; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.math.BigDecimal; 9 | 10 | @Service 11 | @AllArgsConstructor 12 | public class OrderService { 13 | public OrderMapper orderMapper; 14 | 15 | /** 16 | * 下单 17 | */ 18 | public boolean createOrder(Long skuId, Integer quantity) { 19 | Order order = new Order(); 20 | order.setSkuId(skuId); 21 | order.setQuantity(quantity); 22 | order.setPrice(BigDecimal.valueOf(6000)); 23 | return orderMapper.insert(order) > 0; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/java/mybatis/mate/sharding/jta/atomikos/service/SkuService.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.jta.atomikos.service; 2 | 3 | import lombok.AllArgsConstructor; 4 | import mybatis.mate.sharding.jta.atomikos.entity.Sku; 5 | import mybatis.mate.sharding.jta.atomikos.mapper.SkuMapper; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | @AllArgsConstructor 10 | public class SkuService { 11 | private SkuMapper skuMapper; 12 | 13 | /** 14 | * 减少库存 15 | */ 16 | public boolean reduceStock(Long id, Integer stock, boolean error) { 17 | if(error) { 18 | throw new RuntimeException("制造一个异常,测试事务"); 19 | } 20 | Sku sku = new Sku(); 21 | sku.setId(id); 22 | sku.setStock(stock); 23 | return skuMapper.updateById(sku) > 0; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Mybatis Mate 配置 2 | mybatis-mate: 3 | cert: 4 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 5 | grant: thisIsTestLicense 6 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 7 | sharding: 8 | health: true # 健康检测 9 | primary: test # 默认选择数据源,该项配置必须有否则无法加载启动 10 | datasource: 11 | test: 12 | # 数据源 test 节点 1 13 | - key: t1 14 | driver-class-name: com.mysql.cj.jdbc.Driver 15 | url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 16 | username: root 17 | test2: 18 | # 数据源 test2 节点 1 19 | - key: t1 20 | driver-class-name: com.mysql.cj.jdbc.Driver 21 | url: jdbc:mysql://localhost:3306/test2?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 22 | username: root 23 | test3: 24 | # 数据源 test3 节点 1 25 | - key: t1 26 | driver-class-name: org.postgresql.Driver 27 | url: jdbc:postgresql://localhost:5432/test 28 | username: postgres 29 | password: 123456 30 | 31 | # 允许bean定义重写 32 | spring: 33 | main: 34 | allow-bean-definition-overriding: true 35 | 36 | # 配置健康检查 37 | management: 38 | endpoint: 39 | health: 40 | show-details: always 41 | health: 42 | defaults: 43 | enabled: false 44 | db: 45 | enabled: true 46 | 47 | # Logger Config 48 | logging: 49 | level: 50 | mybatis.mate: debug 51 | org.apache: debug 52 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/resources/db/log-db3.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS "public"."log"; 2 | CREATE TABLE "public"."log" ( 3 | "id" int8 NOT NULL, 4 | "content" varchar(500) COLLATE "pg_catalog"."default" 5 | ) 6 | ; 7 | COMMENT ON COLUMN "public"."log"."id" IS '主键'; 8 | COMMENT ON COLUMN "public"."log"."content" IS '内容'; 9 | 10 | ALTER TABLE "public"."log" ADD CONSTRAINT "log_pkey" PRIMARY KEY ("id"); 11 | -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/resources/db/order-db1.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS t_order; 2 | 3 | CREATE TABLE t_order 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键 ID', 6 | sku_id BIGINT(20) NOT NULL COMMENT 'SKU ID', 7 | quantity INT(2) NULL DEFAULT NULL COMMENT '数量', 8 | price decimal(20, 2) NULL DEFAULT NULL COMMENT '价格', 9 | PRIMARY KEY (id) 10 | ); 11 | 12 | DELETE FROM t_order; 13 | 14 | INSERT INTO t_order (id, sku_id, quantity, price) VALUES (1, 3, 1, 5999.9); -------------------------------------------------------------------------------- /mybatis-mate-sharding-jta-atomikos/src/main/resources/db/sku-db2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS sku; 2 | 3 | CREATE TABLE sku 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键 ID', 6 | product VARCHAR(30) NULL DEFAULT NULL COMMENT '商品', 7 | color VARCHAR(30) NULL DEFAULT NULL COMMENT '颜色', 8 | stock INT(10) NULL DEFAULT NULL COMMENT '库存', 9 | PRIMARY KEY (id) 10 | ); 11 | 12 | DELETE FROM sku; 13 | 14 | INSERT INTO sku (id, product, color, stock) VALUES (3, 'huawei mate30', '银白', 100); -------------------------------------------------------------------------------- /mybatis-mate-sharding/build.gradle: -------------------------------------------------------------------------------- 1 | description "数据库分库分表多数动态据源示例" 2 | 3 | dependencies { 4 | implementation("org.springframework.boot:spring-boot-starter-actuator") 5 | implementation("org.postgresql:postgresql") 6 | implementation("mysql:mysql-connector-java") 7 | 8 | testImplementation("org.springframework.boot:spring-boot-starter-test") 9 | testImplementation("junit:junit") 10 | } 11 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.baomidou 6 | mybatis-mate-examples 7 | 0.0.1-SNAPSHOT 8 | 9 | 4.0.0 10 | mybatis-mate-sharding 11 | 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-actuator 16 | 17 | 18 | org.postgresql 19 | postgresql 20 | 21 | 22 | mysql 23 | mysql-connector-java 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-maven-plugin 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/ShardingApplication.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ShardingApplication { 8 | 9 | // 测试访问 http://localhost:8080/test 10 | public static void main(String[] args) { 11 | SpringApplication.run(ShardingApplication.class, args); 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/config/DdlConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.config; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.DdlScript; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import javax.sql.DataSource; 8 | 9 | @Configuration 10 | public class DdlConfig { 11 | 12 | /** 13 | * 注入脚本执行类,支持自定义执行脚本 14 | */ 15 | @Bean 16 | public DdlScript ddlScript(DataSource dataSource) { 17 | return new DdlScript(dataSource); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/config/MyShardingProcessor.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.config; 2 | 3 | import mybatis.mate.sharding.IShardingProcessor; 4 | import mybatis.mate.sharding.ShardingKey; 5 | import org.apache.ibatis.mapping.MappedStatement; 6 | import org.apache.ibatis.plugin.Invocation; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.transaction.support.TransactionSynchronizationManager; 9 | 10 | /** 11 | * 这个类可以自行控制 datasourceKey 12 | */ 13 | @Component 14 | public class MyShardingProcessor implements IShardingProcessor { 15 | 16 | @Override 17 | public boolean changeDatasource(Invocation invocation, MappedStatement mappedStatement, String datasourceKey) { 18 | System.out.println("ThreadLocal 缓存 datasourceKey = " + datasourceKey); 19 | 20 | if (TransactionSynchronizationManager.isActualTransactionActive()) { 21 | // 在同一个事务不执行切换数据源逻辑 22 | return true; 23 | } 24 | 25 | // 这里返回 true 将切换到指定 datasourceKey 对应数据源,返回 false 按默认规则自动切换 26 | // 切换到指定 datasourceKey 数据源调用 ShardingKey.change("mysqlt2"); 记得返回 true 切换成功 27 | 28 | // false 会调用策略 true 当前内部处理 datasourceKey 该类和策略类不是必须都要 29 | 30 | return false; 31 | } 32 | 33 | @Override 34 | public void clearDatabaseKey(Invocation invocation, MappedStatement mappedStatement, String datasourceKey) { 35 | System.out.println("清理 ThreadLocal 缓存 datasourceKey = " + datasourceKey); 36 | 37 | // 如果要保持 datasourceKey 一直在一个线程中可以不用清理,以下代码删除即可 38 | ShardingKey.clearDatabaseKey(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/config/MyShardingStrategy.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.config; 2 | 3 | import mybatis.mate.sharding.ShardingDatasource; 4 | import mybatis.mate.strategy.RandomShardingStrategy; 5 | import org.apache.ibatis.mapping.SqlCommandType; 6 | import org.apache.ibatis.plugin.Invocation; 7 | 8 | /** 9 | * 自定义策略,打开注释 @Component 实现自己的逻辑 10 | *

11 | * 默认策略 {@link RandomShardingStrategy} 12 | *

13 | */ 14 | //@Component 15 | public class MyShardingStrategy extends RandomShardingStrategy { 16 | 17 | /** 18 | * 决定切换数据源 key {@link ShardingDatasource} 19 | * 20 | * @param group 动态数据库组 21 | * @param invocation {@link Invocation} 22 | * @param sqlCommandType {@link SqlCommandType} 23 | */ 24 | @Override 25 | public void determineDatasourceKey(String group, Invocation invocation, SqlCommandType sqlCommandType) { 26 | // 数据源组 group 自定义选择即可, keys 为数据源组内主从多节点,可随机选择或者自己控制 27 | this.changeDatabaseKey(group, sqlCommandType, keys -> chooseKey(keys, invocation)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/config/MysqlDdl.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.config; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.IDdl; 4 | import lombok.AllArgsConstructor; 5 | import mybatis.mate.config.ShardingGroupProperty; 6 | import mybatis.mate.sharding.ShardingDatasource; 7 | import mybatis.mate.sharding.ShardingKey; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.sql.DataSource; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | import java.util.function.Consumer; 14 | 15 | @Component 16 | @AllArgsConstructor 17 | public class MysqlDdl implements IDdl { 18 | private ShardingDatasource shardingDatasource; 19 | 20 | @Override 21 | public void runScript(Consumer consumer) { 22 | // 多数据源指定,主库初始化从库自动同步 23 | String group = "mysql"; 24 | ShardingGroupProperty sgp = ShardingKey.getDbGroupProperty(group); 25 | if (null != sgp) { 26 | // 主库 27 | sgp.getMasterKeys().forEach(key -> { 28 | consumer.accept(shardingDatasource.getDataSource(group + key)); 29 | }); 30 | // 从库 31 | sgp.getSlaveKeys().forEach(key -> { 32 | consumer.accept(shardingDatasource.getDataSource(group + key)); 33 | }); 34 | } 35 | } 36 | 37 | /** 38 | * 执行 SQL 脚本方式 39 | */ 40 | @Override 41 | public List getSqlFiles() { 42 | return Arrays.asList( 43 | "db/user-mysql.sql" 44 | // ,"db/user-data.sql" 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/config/PostgresDdl.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.config; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.IDdl; 4 | import lombok.AllArgsConstructor; 5 | import mybatis.mate.sharding.ShardingDatasource; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.sql.DataSource; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.function.Consumer; 12 | 13 | @Component 14 | @AllArgsConstructor 15 | public class PostgresDdl implements IDdl { 16 | private ShardingDatasource shardingDatasource; 17 | 18 | @Override 19 | public void runScript(Consumer consumer) { 20 | // 多数据源指定,主库初始化从库自动同步 21 | // postgrest2 = postgres(数据源group) + t1(数据源key) 22 | consumer.accept(shardingDatasource.getDataSource("postgrest1")); 23 | } 24 | 25 | /** 26 | * 执行 SQL 脚本方式 27 | */ 28 | @Override 29 | public List getSqlFiles() { 30 | return Arrays.asList( 31 | "db/user-postgres.sql" 32 | // ,"db/user-data.sql" 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/config/ScheduledConfig.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import mybatis.mate.sharding.ShardingHealthIndicator; 6 | import org.springframework.boot.actuate.health.Health; 7 | import org.springframework.scheduling.annotation.EnableScheduling; 8 | import org.springframework.scheduling.annotation.Scheduled; 9 | import org.springframework.stereotype.Component; 10 | 11 | 12 | /** 13 | * 如果外部未调用 spring boot 的健康检查 ... 14 | *

15 | * 可以如下使用定时任务检查数据库健康状况,这个方法不是必须的 16 | */ 17 | @Slf4j 18 | @Component 19 | @EnableScheduling // 这个开启定时任务,注意请勿重复设置 20 | @AllArgsConstructor 21 | public class ScheduledConfig { 22 | private ShardingHealthIndicator shardingHealthIndicator; 23 | 24 | /** 25 | * 每 15 秒执行一次,健康检查 26 | */ 27 | @Scheduled(cron = "0/15 * * * * ? ") 28 | public void dbHealthCheck() { 29 | Health health = shardingHealthIndicator.health(); 30 | log.debug("Sharding health: {}", health.toString()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.controller; 2 | 3 | import com.baomidou.mybatisplus.extension.ddl.DdlScript; 4 | import lombok.AllArgsConstructor; 5 | import mybatis.mate.sharding.ShardingKey; 6 | import mybatis.mate.sharding.service.UserService; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import java.io.StringReader; 11 | 12 | @RestController 13 | @AllArgsConstructor 14 | public class UserController { 15 | private DdlScript ddlScript; 16 | private UserService userService; 17 | 18 | // 测试访问 http://localhost:8080/test 19 | @GetMapping("/test") 20 | public boolean testSharding() throws Exception { 21 | this.initMysqlT2(); 22 | return userService.test(); 23 | } 24 | 25 | // 测试访问 http://localhost:8080/test2 26 | @GetMapping("/test2") 27 | public boolean testSharding2() throws Exception { 28 | this.initMysqlT2(); 29 | return userService.testRw(); 30 | } 31 | 32 | public void initMysqlT2() throws Exception { 33 | // 切换到 mysql 从库,执行 SQL 脚本 34 | ShardingKey.change("mysqlt2"); 35 | ddlScript.run(new StringReader("DELETE FROM user;\n" + 36 | "INSERT INTO user (id, username, password, sex, email) VALUES\n" + 37 | "(20, 'Duo', '123456', 0, 'Duo@baomidou.com');")); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/entity/User.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | /** 8 | * 9 | */ 10 | @Getter 11 | @Setter 12 | @ToString 13 | public class User { 14 | private Long id; 15 | private String username; 16 | private String password; 17 | private Integer sex; 18 | private String email; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import mybatis.mate.annotation.Sharding; 5 | import mybatis.mate.sharding.config.MyShardingStrategy; 6 | import mybatis.mate.sharding.entity.User; 7 | import org.apache.ibatis.annotations.Mapper; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | @Mapper 11 | //@Sharding("mysql") 12 | public interface UserMapper extends BaseMapper { 13 | 14 | @Sharding(value = "postgres", strategy = MyShardingStrategy.class) 15 | @Select("select id from \"public\".\"user\" where username=#{username}") 16 | Long selectByUsername(String username); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/java/mybatis/mate/sharding/service/UserService.java: -------------------------------------------------------------------------------- 1 | package mybatis.mate.sharding.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.toolkit.IdWorker; 5 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 6 | import jakarta.annotation.Resource; 7 | import mybatis.mate.sharding.entity.User; 8 | import mybatis.mate.sharding.mapper.UserMapper; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | @Service 13 | public class UserService { 14 | @Resource 15 | private UserMapper mapper; 16 | final String TEST_USER_NAME = "青苗"; 17 | 18 | public boolean test() { 19 | 20 | // 插入 mysql t1 主库 21 | this.insertT1(); 22 | 23 | // mysql t2 从库未做同步,这里是查不出结果的 24 | Long count = mapper.selectCount(getWrapperByUsername(TEST_USER_NAME)); 25 | if (count > 0) { 26 | System.err.println("不符合执行预期"); 27 | return false; 28 | } 29 | 30 | // mysql t2 查初始化 Duo 记录 31 | System.err.println(mapper.selectCount(getWrapperByUsername("Duo")) == 1); 32 | 33 | // 切换数据源 postgres 查询 Tom 记录 34 | Long id = mapper.selectByUsername("Tom"); 35 | System.err.println(null != id && id.equals(3L)); 36 | return true; 37 | } 38 | 39 | @Transactional 40 | public boolean testRw() { 41 | 42 | // 插入 mysql t1 主库 43 | this.insertT1(); 44 | 45 | // 区别 test() 例子,这里是同一个事务不切换数据源,直接查询 t1 的数据库 46 | Long count = mapper.selectCount(getWrapperByUsername(TEST_USER_NAME)); 47 | if (count < 1) { 48 | System.err.println("不符合执行预期"); 49 | return false; 50 | } 51 | 52 | return true; 53 | } 54 | 55 | private void insertT1() { 56 | // 删除历史数据 57 | mapper.delete(Wrappers.lambdaQuery().eq(User::getUsername, TEST_USER_NAME)); 58 | // 插入 mysql t1 主库 59 | User user = new User(); 60 | user.setId(IdWorker.getId()); 61 | user.setUsername(TEST_USER_NAME); 62 | user.setSex(1); 63 | user.setEmail("jobob@qq.com"); 64 | user.setPassword("123"); 65 | mapper.insert(user); 66 | } 67 | 68 | protected LambdaQueryWrapper getWrapperByUsername(String username) { 69 | return Wrappers.lambdaQuery().eq(User::getUsername, username); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Mybatis Mate 配置 2 | mybatis-mate: 3 | cert: 4 | # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 5 | grant: thisIsTestLicense 6 | license: Qw46ncaiXykSqBByQDTGLFmior/pd8kzu3B4aR1BW3SQkXer4DtwQ0o5f6LNqjnUg3qRSo/3w+UmqYoSXA8ZBrTf16OcXFbLl7V3WRCBLeoRDi1c9BTQjumEzt/8HTzM0n+/hg+GU57OJbDvBZQI40U3abKT84qCW0EqjNA2Kg4fOlaHhXn6w3mEHXc3aMw8H+rBtxWSXyZOYUp83QVcTfh+n9sGDeys3NF7zjOrFxb24wB5DTpg7yirXnjeZznqPFwnyu45mACLPP4T8rFjHlW18+Pv2xoqlUCXx4QRsdBQEUDi26u4z0dba+O2S/vl7QGNfXZvGhbmv59IJK/FLA== 7 | sharding: 8 | health: true # 健康检测数据源需要设置 SQL 检测语句 test-query: select 1 9 | primary: mysql # 默认选择数据源,该项配置必须有否则无法加载启动 10 | datasource: 11 | mysql: 12 | - key: t1 13 | driver-class-name: com.mysql.cj.jdbc.Driver 14 | url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 15 | username: root 16 | schema: test 17 | test-query: select 1 18 | - key: t2 19 | cluster: slave # 从库读写分离时候负责 sql 查询操作,主库 master 默认可以不写 20 | driver-class-name: com.mysql.cj.jdbc.Driver 21 | url: jdbc:mysql://localhost:3306/test2?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 22 | username: root 23 | schema: test2 24 | test-query: select 1 25 | hikari: 26 | maxLifetime: 1765000 27 | maximumPoolSize: 10 28 | minimum-idle: 3 29 | postgres: 30 | - key: t1 31 | driver-class-name: org.postgresql.Driver 32 | url: jdbc:postgresql://localhost:5432/test 33 | username: postgres 34 | password: 123456 35 | schema: test 36 | test-query: select 1 37 | hikari: 38 | maxLifetime: 1765000 39 | maximumPoolSize: 10 40 | minimum-idle: 3 41 | 42 | # 允许bean定义重写 43 | spring: 44 | main: 45 | allow-bean-definition-overriding: true 46 | 47 | # 配置健康检查 48 | management: 49 | endpoint: 50 | health: 51 | show-details: always 52 | health: 53 | defaults: 54 | enabled: false 55 | db: 56 | enabled: true 57 | 58 | # Logger Config 59 | logging: 60 | level: 61 | mybatis.mate: debug 62 | org.apache: debug 63 | -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/resources/db/user-mysql.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS user; 2 | 3 | CREATE TABLE user 4 | ( 5 | id BIGINT(20) NOT NULL COMMENT '主键ID', 6 | username VARCHAR(30) NULL DEFAULT NULL COMMENT '用户名', 7 | password VARCHAR(1000) NULL DEFAULT NULL COMMENT '密码', 8 | sex INT(2) NULL DEFAULT NULL COMMENT '性别', 9 | email VARCHAR(1000) NULL DEFAULT NULL COMMENT '邮箱', 10 | PRIMARY KEY (id) 11 | ); 12 | 13 | DELETE FROM user; 14 | 15 | INSERT INTO user (id, username, password, sex, email) VALUES 16 | (1, 'Jone', '123456', 1, 'test1@baomidou.com'), 17 | (2, 'Jack', '123456', 0, 'test2@baomidou.com'); -------------------------------------------------------------------------------- /mybatis-mate-sharding/src/main/resources/db/user-postgres.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS "public"."user"; 2 | 3 | CREATE TABLE "public"."user" ( 4 | "id" int8 NOT NULL, 5 | "username" varchar(255) NOT NULL, 6 | "password" varchar(255) NOT NULL, 7 | "sex" int2 NOT NULL, 8 | "email" varchar(255) NOT NULL, 9 | PRIMARY KEY ("id") 10 | ); 11 | 12 | COMMENT ON COLUMN "public"."user"."id" IS '主键 ID'; 13 | COMMENT ON COLUMN "public"."user"."username" IS '用户名'; 14 | COMMENT ON COLUMN "public"."user"."password" IS '密码'; 15 | COMMENT ON COLUMN "public"."user"."sex" IS '性别'; 16 | COMMENT ON COLUMN "public"."user"."email" IS '电子邮箱'; 17 | 18 | DELETE FROM "public"."user"; 19 | 20 | INSERT INTO "public"."user" (id, username, password, sex, email) VALUES 21 | (3, 'Tom', '123456', 1, 'test3@baomidou.com'); 22 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | // MybatisPlus 企业级模块 2 | rootProject.name = 'mybatis-mate-examples' 3 | 4 | include 'mybatis-mate-audit' 5 | include 'mybatis-mate-datascope' 6 | include 'mybatis-mate-ddl-mysql' 7 | include 'mybatis-mate-ddl-postgres' 8 | include 'mybatis-mate-ddl-oracle' 9 | include 'mybatis-mate-dict' 10 | include 'mybatis-mate-encrypt' 11 | include 'mybatis-mate-encrypt-mysql-aes' 12 | include 'mybatis-mate-encrypt-sm2-sm3-sm4' 13 | include 'mybatis-mate-hot-reload' 14 | include 'mybatis-mate-jsonbind' 15 | include 'mybatis-mate-sensitive-jackson' 16 | include 'mybatis-mate-sensitive-words' 17 | include 'mybatis-mate-sharding' 18 | include 'mybatis-mate-sharding-dynamic' 19 | include 'mybatis-mate-sharding-jta-atomikos' 20 | -------------------------------------------------------------------------------- /国密SM2.3.4算法使用规范/SM2密码算法使用规范.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baomidou/mybatis-mate-examples/49536203f7240b13a95e5dbf5a6e82314bad515e/国密SM2.3.4算法使用规范/SM2密码算法使用规范.pdf -------------------------------------------------------------------------------- /国密SM2.3.4算法使用规范/国密算法SM2-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baomidou/mybatis-mate-examples/49536203f7240b13a95e5dbf5a6e82314bad515e/国密SM2.3.4算法使用规范/国密算法SM2-1.pdf -------------------------------------------------------------------------------- /国密SM2.3.4算法使用规范/国密算法SM2-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baomidou/mybatis-mate-examples/49536203f7240b13a95e5dbf5a6e82314bad515e/国密SM2.3.4算法使用规范/国密算法SM2-2.pdf -------------------------------------------------------------------------------- /国密SM2.3.4算法使用规范/国密算法SM3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baomidou/mybatis-mate-examples/49536203f7240b13a95e5dbf5a6e82314bad515e/国密SM2.3.4算法使用规范/国密算法SM3.pdf -------------------------------------------------------------------------------- /国密SM2.3.4算法使用规范/国密算法SMS4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baomidou/mybatis-mate-examples/49536203f7240b13a95e5dbf5a6e82314bad515e/国密SM2.3.4算法使用规范/国密算法SMS4.pdf --------------------------------------------------------------------------------