# ibit-mybatis **Repository Path**: ibit-tech/ibit-mybatis ## Basic Information - **Project Name**: ibit-mybatis - **Description**: mybatis扩展 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-06-04 - **Last Updated**: 2020-12-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ibit-mybatis 2.x 介绍 ## 概述    ibit-mybatis 是一个 Mybatis 的增强工具,在 Mybatis 的基础上增加了新的特性与功能,志在简化开发流程、提高开发效率。
### 特性 * 无侵入,引入”ibit-mybatis”对现有工程不会产生影响。 * 无 xml 配置,基于注解的方式实现 * 灵活的CRUD(增、删、改、查)操作,Mapper,支持常用的单表CRUD操作,更有强大的SQL构造器([sql-builder](https://github.com/ibit-tech/sql-builder)),满足更为复杂的操作(如聚合函数、分组、连表、分页),为了让sql-builder更好的支持 ibit-mybatis,从 ibit-mybatis 2.0 开始,sql-builder 合并到 ibit-mybatis 中。 * 内置代码生成器([ibit-mybatis-generator](https://github.com/ibit-tech/ibit-mybatis-generator)),指定数据库表,自动生成Mapper(无主键、单主键和多主键 Mapper)、Entity、Properties等基础类,减少重复或者相似代码编写。 * 扩展支持,数据脱敏(后续支持) ### sql-builder描述 `sql-builder`定义动态SQL的生成规则,用来实现单表的CRUD操作。 #### 核心 sql 接口 详细 api 文档参考:[ibit-mybatis 2.x API 文档](https://ibit.tech/apidocs/ibit-mybatis/2.x/index.html) | 说明 | 接口 | | --- | --- | | 搜索 | [QuerySql](https://ibit.tech/apidocs/ibit-mybatis/2.x/index.html) | | 计数 | [CountSql](https://ibit.tech/apidocs/ibit-mybatis/2.x/index.html) | | 删除 | [DeleteSql](https://ibit.tech/apidocs/ibit-mybatis/2.x/index.html) | | 插入 | [InsertSql](https://ibit.tech/apidocs/ibit-mybatis/2.x/index.html) | | 更新 | [UpdateSql](https://ibit.tech/apidocs/ibit-mybatis/2.x/index.html) | #### sql 接口支持 不同类型的 sql, 其语句的约束不一样,下表列举所有的语句支持。 | 接口 | 支持方法 | 说明 | | --- | --- | --- | | ColumnSupport | column
columnPo | `SELECT column1[, column2...]` 语句| | DeleteSupport | delete | `DELETE t1.*` 语句| | DistinctSupport | distinct | `DISTINCT` 语句 | | FromSupport | from | `FROM table1 t1[, table2 t2...]` 语句| | GroupBySupport | groupBy | `GROUP BY t1.column1[, t2.column2, ...]`语句| | HavingSupport | having
andHaving
orHaving | `HAVING`语句| | InsertTableSupport | insert | `INSERT INTO table1 t1` 语句, t1表示 "表别名" | | JoinOnSupport | joinOn
leftJoinOn
rightJoinOn
fullJoinOn
innerJoinOn
complexLeftJoinOn
complexRightJoinOn
complexFullJoinOn
complexInnerJoinOn | `[LEFT\|RIGHT\|FULL\|INNER] JOIN ON`语句 | | LimitSupport | limit | `LIMIT #{start}, #{limit}`语句 | | OrderBySupport | orderBy | `ORDER BY` 语句 | | SetSupport | set | SET 条件语句 | | UpdateTableSupport | update | `UPDATE table1 t1[, table2 t2...]`语句,t1,t2表示"表别名" | | ValuesSupport | values | `(column1, column2, ...) VALUES(?, ?, ...)`语句 | | WhereSupport | where
andWhere
orWhere | `WHERE` 语句 | | OnDuplicateKeyUpdateSupport | onDuplicateKeyUpdate | `ON DUPLICATE KEY UPDATE column1 = ? [, column2= ?...]` 语句 | | IColumnFullTextSupport | fullText
fullTextMatch | `MATCH(column1 [, column2, ...]) AGAINST(? [IN (BOOLEAN \| NATURAL LANGUAGE) MODE])` 语句 | #### sql 工厂类 工厂类:`tech.ibit.mybatis.sqlbuilder.SqlFactory`,一般不直接使用,继承 `RawMapper` 的 Mapper 可直接创建 `QuerySql`、`CountSql`、`DeleteSql`、`InsertSql` 和 `UpdateSql` 对应实例。 ### Mapper 说明 #### Mapper 基础支持 `ibit-mybatis` 定义了 5 种 Mapper,分别是 `RawMapper`,`Mapper`, `NoIdMapper`,`SingleIdMapper`,`MultipleIdMapper`。以下分别说明。 | Mapper 类型 | 父接口 | 说明 | | --- | --- | --- | | RawMapper | / | 基于注解方式增、删、改、查| | Mapper | RawMapper | 在 RawMapper 增加 Sql 实例创建,unique key 查询默认方法 | | NoIdMapper | Mapper | 扩展无主键表的增 | | SingleIdMapper | Mapper | 扩展单主键表的根据id增、删、改、查 | | MultipleIdMapper | Mapper | 扩展多主键表的根据id增、删、改、查 | 使用 [ibit-mybatis-generator](https://github.com/ibit-tech/ibit-mybatis-generator) 2.x 版本,会根据表主键数量,继承不同的 Mapper。 #### Mapper 结合 Sql 自定义增、删、改、查 | Mapper 创建 Sql 实例方法 | 实例类型 | 实例执行方法说明 | | --- | --- | --- | | createQuery | QuerySql | executeQueryPage:查询(包含分页信息)
executeQuery:查询列表
executeQueryOne:查询单条
executeQueryDefaultPage:查询基本类型(包含分页信息)
executeQueryDefault:查询基本类型| | createCount | CountSql | executeCount:计数 | | createDelete | DeleteSql | executeDelete:执行删除 | | createInsert | InsertSql | executeInsert:执行插入
executeInsertWithGenerateKeys:执行插入并生成主键 | | createUpdate | UpdateSql | executeUpdate:执行更新| 自定义查询例子: ``` public User getByUsername(String username) { if (StringUtils.isBlank(username)) { return null; } return mapper .createQuery() .columnPo(User.class) .from(UserProperties.TABLE) .andWhere(UserProperties.username.eq(username)) .limit(1) .executeQueryOne(); } // 如果 mapper 的实体类型为User,则可以简化为以下方式 public User getByUsername(String username) { if (StringUtils.isBlank(username)) { return null; } return mapper .createQuery() .andWhere(UserProperties.username.eq(username)) .limit(1) .executeQueryOne(); } ``` ## 用法 ### 相关引用 #### Gradle ``` compile 'tech.ibit:ibit-mybatis:${lastest}' ``` #### Maven ``` tech.ibit ibit-mybatis ${latest} ``` **说明**: 将 "${latest}" 替换成 `2.0` 以上版本。 ### 配置说明 需要将 Mybatis Configuration 的 `mapUnderscoreToCamelCase` 的值设置为 true。 **方式1**:使用 mybatis-config.xml ``` ``` **方式2**:java 代码方式 ``` Configuration configuration = new Configuration(environment); configuration.setMapUnderscoreToCamelCase(true); ``` **方式3**:使用了 `mybatis-spring-boot-starter`,修改配置如下 ``` # 字段映射驼峰 mybatis.configuration.map-underscore-to-camel-case=true ``` ### 其他说明 #### 指定 CommonEnumTYpeHandler `ibit-mybatis` 定义了枚举类型(`CommonEnum`,枚举-Integer转换),其`TypeHandler`为 `CommonEnumTypeHandler`。 如果使用 `CommonEnum` 作为系统通用枚举类,则需要做以下改造。 **a.** 新的枚举需要实现`CommonEnum#getValue`方法。 **b.** SqlProvider 需要做配置 ``` SqlProvider.setValueFormatter(new LinkedHashMap>() {{ put(tech.ibit.mybatis.CommonEnum.class, o -> ((tech.ibit.mybatis.CommonEnum) o).getValue()); }}); ``` **c.** 修改默认的枚举 TypeHandler **方式1**:配置mybatis-config.xml ``` ``` **方式2**:java 代码方式 ``` Configuration configuration = new Configuration(environment); configuration.setDefaultEnumTypeHandler(tech.ibit.mybatis.CommonEnumTypeHandler.class); ``` **方式3**:使用了 `mybatis-spring-boot-starter`,修改配置如下 ``` # 指定默认的枚举处理类 mybatis.configuration.default-enum-type-handler=tech.ibit.mybatis.CommonEnumTypeHandler ``` ### 版本升级说明 #### ibit\-mybatis 从 2.0 升级到 2.1+ 需要做的事情,针对生成的 `mapper` 继承 `SingleIdMapper`、`MultipleIdMapper` 和 `NoIdMapper` 的接口,需要重载以下方法 ``` /** * 获取默认的表对象 * * @return 表对象 */ @Override default Table getDefaultTable() { return %propertyName%.TABLE; } ``` 继承`SingleIdMapper`需要再重载以下方法: ``` /** * 获取主键列 * * @return 主键列 */ @Override default Column getId() { return %propertyName%.%idColumn%; } ``` 最简单的方式,就是拿 ibit-mybatis-generator 2.1 重新生成一下 mapper 即可。 #### 升级到2.6+,需要增加拦截类`ResultMapInterceptor`,动态指定`ResultType` tech.ibit.mybatis.plugin.ResultMapInterceptor **相关用例**: ``` /** * 按照用户类型统计数量 * * @return 用户类型统计 */ @Override public List listTypeTotals() { return mapper.createQuery() .column(UserProperties.type) .column(UserProperties.type.count("total")) .groupBy(UserProperties.type) .orderBy(UserProperties.type.orderBy()) .executeQuery(UserTypeTotal.class); } ``` **方式1**:配置mybatis-config.xml ``` ``` **方式2**:配置Bean ``` @Bean public ResultMapInterceptor getResultMapInterceptor() { return new ResultMapInterceptor(); } ``` #### 升级到版本 2.9+ 使用 `ibit-mybatis` 版本 2.9+,需要用 `ibit-mybatis-generator` 版本 2.3+ 重新生成一下 `Properties` 类。 **改动点:** Column 标识 字段是否为主键,是否自增,是否可以为null等。 ``` /** * 用户id */ Column userId = Column.getIdInstance(TABLE, "user_id", true); /** * 用户名称 */ Column name = Column.getInstance(TABLE, "name"); ``` ### 新功能介绍 #### 2.6 新增mysql全文搜索 ``` /** * 给出搜索关键字,查找名称关联度 * * @param keyword 查询关键字 * @return 名称关联度 */ public List listUserNameScores(String keyword) { if (StringUtils.isBlank(keyword)) { return Collections.emptyList(); } FullTextColumn score = UserProperties.userName.fullText(new IColumn[]{UserProperties.nickName}, keyword, "score"); return mapper.createQuery() .column(Arrays.asList( UserProperties.userId, UserProperties.nickName, UserProperties.userName, score)) .andHaving(score.gt(0)) .orderBy(score.orderBy(true)) .executeQuery(UserNameScoreDto.class); } /** * 给出关键字,全文搜索用户名或者昵称 * * @param keyword 查询关键字 * @return 用户名列表 */ public List listUsers(String keyword) { if (StringUtils.isBlank(keyword)) { return Collections.emptyList(); } return mapper.createQuery() .column(Arrays.asList( UserProperties.userId, UserProperties.userName, UserProperties.nickName )) .andWhere(UserProperties.userName.fullTextMatch(new IColumn[]{UserProperties.nickName}, keyword)) .executeQuery(UserNameDto.class); } ``` #### 2.10 新增了字段加密功能拦截器 ** ResultDecryptInterceptor**:`tech.ibit.mybatis.plugin.ResultDecryptInterceptor` 定义解密拦截器,针对返回的对象解密。 构造函数如下: ``` public ResultDecryptInterceptor(TransferStrategy strategy) { this.strategy = strategy; } ``` 加解密策略需要实现接口 `tech.ibit.mybatis.plugin.strategy.TransferStrategy`。 解密类需要,类和字段使用`tech.ibit.mybatis.plugin.annotation.Encrypt`注解。如: ``` @Encrypt class User { private String username; @Encrypt private String email; @Encrypt private String password; @Encrypt private String idCardNo; // 省略构造函数.. Getter 和 Setter 方法 } ``` ** ParameterEncryptInterceptor**:`tech.ibit.mybatis.plugin.ParameterEncryptInterceptor` 入参对象加密拦截器。 构造函数如下: ``` /** * 参数加密 * * @param columnsToEncrypt 参数加密 * @param strategy 加密策略 */ public ParameterEncryptInterceptor(Set columnsToEncrypt, TransferStrategy strategy) { this.columnsToEncrypt = columnsToEncrypt; this.strategy = strategy; } ``` 指定需要加密的列,加解密策略需要实现接口 `tech.ibit.mybatis.plugin.strategy.TransferStrategy`。 ## 公众号 喜欢我的文章,请关注公众号 ![iBit程序猿](https://x-halo.oss-cn-beijing.aliyuncs.com/halo/wechat_1589272852710.jpg)