All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.README.md Maven / Gradle / Ivy

Go to download

Mybatis generic mapper plugin for solving most basic operations, simplifying sql syntax and improving dynamic execution efficiency

There is a newer version: 1.3.7
Show newest version


![MybatisMapper](mybatis-mapper-logo.png)

[![mybatis-mapper](https://img.shields.io/badge/plugin-mybatis--mapper-green?style=flat-square)](https://github.com/tangxbai/mybatis-mappe) [![maven central](https://img.shields.io/badge/maven%20central-v1.3.0-brightgreen?style=flat-square)](https://maven-badges.herokuapp.com/maven-central/org.mybatis/mybatis) ![size](https://img.shields.io/badge/size-196kB-green?style=flat-square) [![license](https://img.shields.io/badge/license-Apache%202-blue?style=flat-square)](http://www.apache.org/licenses/LICENSE-2.0.html)



## 项目简介

Mybatis通用Mapper插件,用于解决大多数基础CRUD,简化sql语法并提高动态执行效率,拥有更丰富的Api。用最少的配置,提供一个健全的使用体系。

*注意:此项目是一款完全开源的项目,您可以在任何适用的场景使用它,商用或者学习都可以,如果您有任何项目上的疑问,可以在issue上提出您问题,我会在第一时间回复您,如果您觉得它对您有些许帮助,希望能留下一个您的星星(★),谢谢。*

------

此项目遵照 [Apache 2.0 License]( http://www.apache.org/licenses/LICENSE-2.0.txt ) 开源许可 

技术讨论QQ群:947460272



## 核心亮点

- **无侵入**:100%兼容mybatis,不与mybatis冲突,只添加功能,对现有程序无任何影响;
- **配置少**:所有配置均在原始mybatis的基础上读取,不增加额外配置消耗;
- **无捆绑关系**:与XML文件独立,有无独立XML均可;
- **效率高**:由Xml+OGNL模式转向Java+ExpressionEngine的模式,省去了XML的解析和OGNL解析的时间消耗;
- **灵活的规则制定**:灵活多元化的(表/列)规则制定,完美融合各种(名字/类型等)不统一的场景;
- **SQL模板语法**:模板语法简单易掌握,一次开发,终生受用,避免因数据库变化而大量更改SQL语句的场景。表达式会在程序完全启动之前编译成完整的SQL,仅留下需要动态解析的表达式,对效率的影响微乎甚微;
- **CRUD增强**:除了提供基础的CRUD外还提供一系列高级辅助方法(Example/ForUpdate/聚合函数/逻辑删除/回收站/乐观锁等);
- **便捷的条件查询**:更简单便捷的Example条件查询,提供符合SQL语义化的链式条件函数调用;
- **支持多主键**:支持多主键场景,CRUD中可选择特定主键进行操作;
- **丰富的主键生成策略**:支持JDBC自增主键、自定义主键SQL查询、雪花ID、UUID、自定义主键生成策略等;
- **支持常量值**:灵活化的常量值生成策略,可针对不同场景做不同操作,均支持雪花ID/UUID等内置生成器;
- **可排序字段**:可对SQL字段排列顺序进行干扰,简直是强迫症重度患者的福音啊;
- **粘连性小**:可以独立使用,纯Java环境/spring/springboot都提供了单独的组件。
- **可扩展的开发模式**:继承Marker/Mapper/BaseMapper即可继续增强基础CRUD。



## 关联文档

关于整合spring,请移步到:https://github.com/tangxbai/mybatis-mapper-spring

关于整合springboot,请移步到:https://github.com/tangxbai/mybatis-mapper-spring-boot



## 项目演示

- java + mybatis-mapper - [点击获取](https://github.com/tangxbai/mybatis-mapper-demo)
- spring + mybatis-mapper - [点击获取](https://github.com/tangxbai/mybatis-mapper-spring-demo)
- springboot + mybatis-mapper - [点击获取](https://github.com/tangxbai/mybatis-mapper-spring-boot/tree/master/mybatis-mapper-spring-boot-samples)



## 功能列表

- [支持模板语法](#支持模板语法)
- [支持SQL注释](#支持SQL注释)
- [支持各种主键生成策略](#支持各种主键生成策略)
- [支持多主键场景](#支持多主键场景)
- [更方便快捷的条件查询](#更方便快捷的条件查询)
- [支持聚合函数统计](#支持聚合函数统计)
- [支持数据库乐观锁](#支持数据库乐观锁)
- [支持各种逻辑删除](#支持各种逻辑删除)
- [支持逻辑删除数据的恢复](#支持逻辑删除数据的恢复)
- [支持查询自定义返回Bean类型](#支持查询自定义返回Bean类型)
- [支持零MapperXML配置文件](#支持零MapperXML配置文件)
- [扩展插件Api](#扩展插件Api)
- [提供各种场景的日志打印](#提供各种场景的日志打印)
- 提供更丰富的API



## 快速开始

Maven方式(**推荐**)

```xml

	com.viiyue.plugins
	mybatis-mapper
	[VERSION]

```

如果你没有使用Maven构建工具,那么可以通过以下途径下载相关jar包,并导入到你的编辑器。

[点击跳转下载页面](https://search.maven.org/search?q=g:com.viiyue.plugins%20AND%20a:mybatis-mapper&core=gav)

![如何下载](https://user-gold-cdn.xitu.io/2019/10/16/16dd24a506f37022?w=995&h=126&f=png&s=14645)

如何获取最新版本?[点击这里获取最新版本](https://search.maven.org/search?q=g:com.viiyue.plugins%20AND%20a:mybatis-mapper&core=gav)



## 如何使用

1、配置 mybatis.xml

这个文件具体如何配置不作过多说明,你可以拉取相关demo查看详细配置,在配置上也没有什么区别,需要注意的是 **typeAliases**(实体别名配置)一定要配置,不然插件可能无法正常工作。

2、配置数据库实体Bean

```java
@Table( prefix = "t_" ) // 表名生成规则,可以配置更多详细说明
@NamingRule( NameStyle.UNDERLINE ) // 字段和数据库列之间的转换规则
@ValueRule( ValueStyle.SHORT ) // 值的生成规则,类似于:#{id}
@ExpressionRule( ExpressionStyle.SHORT ) // 表达式生成规则,类似于: id = #{id}
@DefaultOrderBy( "#pk" ) // #默认排序字段,"pk"为主键占位符,指向当前生效的主键字段,也可以直接写"id"
public class YourModelBean {

    @Id // 主键可以配置多个,但是只会有一个生效,Api方法中如果想要使用其他主键请指明所在下标位置
    @Index( Integer.MIN_VALUE )
    @GeneratedKey( useGeneratedKeys = true ) // JDBC支持的自增主键获取方式
    // @GeneratedKey( valueProvider = SnowFlakeIdValueProvider.class ) // 雪花Id,插件提供的两种主键生成策略之一
    // @GeneratedKey( statement = "MYSQL" ) // 枚举引用
    // @GeneratedKey( statement = "SELECT LAST_INSERT_ID()" ) // 自增主键SQL查询语句
    // @GeneratedKey( statementProvider = YourCustomStatementProvider.class ) // 通过Provider提供SQL语句
    private Long id;

    @Index( Integer.MAX_VALUE - 4 )
    @Column( jdcbType = Type.CHAR ) // 对字段进行详细描述
    @LogicallyDelete( selectValue = "Y", deletedValue = "N" ) // 开启逻辑删除支持,只能配置一次
    private Boolean display;

    @Index( Integer.MAX_VALUE - 3 )
    private Date createTime;

    @Index( Integer.MAX_VALUE - 2 )
    private Date modifyTime;

    @Version // 开启乐观锁支持,只能配置一次
    @Index( Integer.MAX_VALUE - 1 )
    @Column( insertable = false )
    private Long version;
    
    // setter/getter...
    
    // ----------------------------------------------------------------
    // @Index主要对字段出现顺序进行干扰,对字段进行干扰以后,输出的顺序大概是这样:
    // => id, ..., display, create_time, modify_time, version
    // 如果您未使用@Index注解,那么字段的原始顺序是这样的:
    // => id, display, create_time, modify_time, version, ...
    // 默认输出会将父类的字段排在最前面
    // ----------------------------------------------------------------  

}
```

3、Mapper接口需要继承 `BaseMapper` 或者 `Mapper`

```java
// 继承Mapper
public interface YourMapper extends Mapper {
}
// 或者继承BaseMapper
public interface YourMapper extends BaseMapper {
}
```

4、使用方式

```java
SqlSessionFactory factory = new MyBatisMapperFactoryBuilder().build( Resources.getResourceAsStream("your-mybatis.xml"));
SqlSession session = factory.openSession();
YourMapper mapper = session.getMapper(YourMapper.class);
mapper.xxx(...);
session.commit();
```

请注意:**MyBatisMapperFactoryBuilder** 是插件提供的一个 **SqlSessionFactory** 工厂构造器,这里我们需要用插件提供的MyBatisMapperFactoryBuilder替换mybatis原始的 **SqlSessionFactoryBuilder** 以启用插件相关Api功能。



## 配置注解

类型 注解 描述
类注解 @Table 配置表名生成规则
@ResultMap 自定义ResultMap,默认使用BaseResultMap
@Excludes 排除不需要的字段属性,一般用于子类排除父类某字段的场景
@DefaultOrderBy 默认排序字段,#pk内置占位符,隐式地指向当前生效的主键
规则注解 @NamingRule 配置字段名和数据库列的转换规则
@ValueRule 配置值的生成规则,类似:#{id, ...}
@ExpressionRule 配置表达式的生成规则,类似:id = #{id, ...}
以上两种类型的注解都只能配置在类上,主要用于描述数据库实体Bean的一些基础信息,通常建议配置在父类上,进而避免大量重复代码的产生。
成员注解 @Id 主键标识,默认使用第一个标注字段,否则使用primary为true的字段作为主键
@Index 干扰字段的排列顺序,默认按照Bean定义的顺序从父类到子类排列
@Column 显式地配置字段和数据库列的规则说明
@GeneratedKey 主键生成策略,必须和@Id组合使用,否则无效,且只能出现一次
@GeneratedValue 生成常量值,插件提供 SnowFlakeId/UUID,可自行拓展
@Conditional 条件表达式,默认使用 = 桥接前后条件,可更改条件规则
@LogicallyDelete 启用逻辑删除,只能出现一次
@Version 启用乐观锁,只能出现一次
成员注解主要是对实体字段的一些描述
标识注解 @EnableResultMap 标注在Mapper方法上,是否使用ResultMap结果映射
@Reference 标注在Mapper方法上,指向@XXXProvider(type)的其他非同名方法
标识注解主要用于扩展插件Api的时候用的场景多一些,你也可以在自己的Mapper上使用默认的ResultMap,申明一下即可。
## 偏好配置 > 属性说明
属性 描述 类型 默认
enableLogger 是否启用日志 Boolean true
enableMapperScanLog 是否开启Mapper扫描日志 Boolean true
enableRuntimeLog 是否开启实时日志 Boolean true
enableCompilationLog 是否开启编译日志 Boolean true
enableKeywordsToUppercase 关键字大小写转换 Boolean false
databaseColumnStyle 数据库列样式 String #
*特别说明*:`#` 是一个占位符,代表据数据库中的列名,比如mysql中默认列使用 `column`,那么你可以这样配置 `#`,默认是没有任何样式修饰符的。 ```sql -- 默认样式 - # select id, name, age, weight from ... where ... -- Mysql样式 - `#` select `id`, `name`, `age`, `weight` from ... where ... -- Oracle - [#] select [id], [name], [age], [weight] from ... where ... -- 自定义样式 - L-#-R select L-id-R, L-name-R, L-age-R, L-weight-R from ... where ... ``` > 配置方式 ```xml ``` ## 支持模板语法 以下是目前已经支持的模板语法,你可以在自定义 `DynamicProvider` 中无条件的使用它们,也可以开启XML模板语法支持并使用它。 - `@{expression}` - 静态模板,会在程序启动过程中被解析成完整的文本。 - `%{expression}` - 动态模板,会在SQL执行过程被解析成完整的文本,类似mybatis判断条件。 - `[kewords]` - 关键字模板,会根据配置自动转换成大写或小写关键字。 - `{{value.expression}}` - 取值表达式,可以获取执行方法的传入参数或程序上下文数据。 - `message` - 错误信息,用于隐藏错误信息,不影响程序启动,但会在执行过程中抛出。 > 关于this关键字 可能你会在模板看到 `this` 字样的关键字,这个关键字默认指向当前Mapper对应的数据库Bean的 **解析对象**,如果你想在模板语法中使用其他Bean解析对象的话,请使用Mybatis提供的 **类对象别名** 进行调用,这将会类似于 @{this.table} 或者 @{user.table}/@{role.table}/@{xxx.table} 等。 ```java this = EntityParser.getEntity(Bean.class); ``` > 特别说明 首先,插件分两部分,**默认是不支持XML模板语法解析的**,所以可以根据个人喜好,选择开启或者不使用它,插件的运行和XML没太大关系,基础功能是基于Mybatis内部的 `@SelectProvider`、`@UpdateProvider`、`@InsertProvider`、`@DeleteProvider` 注解提供运行所需的 `SqlSource`,所以即使无任何XML文件也可正常工作,因为都是对单表的扩展Api,所以如果涉及一些任何复杂SQL,请添加XML文件并书写自己的SQL逻辑脚本。 > 开启XML模板语法 如果你需要在XML也使用这些模板语法,请配置解析XML的扩展 `LanguageDriver`,插件提供的扩展Driver是 `MyBatisMapperLanguageDriver`,Mybatis的LanguageDriver接口无任何限制,任何人都可以对其进行自定义更改,属于Mybatis的一种扩展机制,具体使用的话,可以在单个XML语句节点上配置 `lang` 属性来开启单个Statement支持,也可以覆盖Mybatis的默认 `XMLLanguageDriver` 解析驱动。 1、单个语句块,使用lang属性即可 ```xml ``` 2、全局范围,需要覆盖mybatis默认语言驱动 ```xml ``` 3、DynamicProvider无条件支持任何模板语法 ```java public final class YourCustomProvider extends DynamicProvider { // 实现一 // 方法名必须和你接口中定义的方法名一致 public String selectAll( MappedStatement ms ) { return "[select] @{this.columns} [from] @{this.table}"; } // 实现二 // 两个参数,第二个为当前对应的Mapper数据库实体Class类型 public String selectAll( MappedStatement ms, Class yourModelBeanType ) { System.out.println(yourModelBeanType); return "[select] @{this.columns} [from] @{this.table}"; } } ``` 接下来对每一种模板语法作一些详细说明,方便大家能更好的理解并熟练的使用它们。现在假设当前Mapper是下面这样的,那么 `this` 关键字会指向 **User的解析对象**,将从其中获取各种元数据信息。 ```java // DO // 省略各种注解配置 public class User { private Long id; private String name; private Integer age; } // Mapper public interface UserMapper extends Mapper { } // DO → User // DTO → UserDTO // PK → Long // this → EntityParser.getEntity(User.class); ``` > @{expression} - 静态模板 ```sql -- 关于表 -- @see com.viiyue.plugins.mybatis.template.builder.TableBuilder @{this.table} → t_user @{this.table.prefix("xxx")} → xxx.t_user @{this.table.alias("t")} → t_user as 't' @{this.table.prefix("xxx").alias("t")} → xxx.t_user as 't' -- 关于单列 -- @see com.viiyue.plugins.mybatis.template.builder.ColumnBuilder @{this.column.yourFieldName} → your_field_name @{this.column.yourFieldName.prefix("a")} → a.your_field_name @{this.column.yourFieldName.suffix("_suffix")} → your_field_name_suffix @{this.column.yourFieldName.javaType} → Integer/Long/YourFieldType @{this.column.yourFieldName.jdbcType} → INT/BIGINT/OTHERS @{this.column.yourFieldName.property} → yourFieldName @{this.column.yourFieldName.prefix("a").suffix("_suffix")} → a.your_field_name_suffix -- 关于所有列 -- @see com.viiyue.plugins.mybatis.template.builder.ColumnsBuilder @{this.columns} → id, name, age @{this.columns.include("id,name")} → id, name @{this.columns.exclude("id,age")} → name @{this.columns.prefix("t")} → t.id, t.name, t.age @{this.columns.prefix("t").include("id,name").exclude("id")} → t.name -- 关于值 -- @see com.viiyue.plugins.mybatis.template.builder.ValuesBuilder @{this.values} → #{id}, #{name}, #{age} @{this.values.alias("user")} → #{user.id}, #{user.name}, #{user.age} @{this.values.include("id,name")} → #{id}, #{name} @{this.values.exclude("id,age")} → #{name} @{this.values.alias("user").include("name,age")} → #{user.name}, #{user.age} -- 关于默认排序(需要在类上配置@DefaultOrderBy) -- 没有配置相关注解的话,表达式返回一段空白文本("") -- @see com.viiyue.plugins.mybatis.template.builder.LogicallyDeleteBuilder @{this.defaultOrderBy} → order by sorter desc @{this.defaultOrderBy.desc} → order by sorter desc @{this.defaultOrderBy.asc} → order by sorter asc @{this.defaultOrderBy.prefix("t")} → order by t.sorter desc -- 关于逻辑删除(需要在字段上配置@LogicallyDelete) -- 没有配置相关注解的话,表达式返回一段空白文本("") -- @see com.viiyue.plugins.mybatis.template.builder.LogicallyDeleteBuilder @{this.tryLogicallyDelete} → deleted = 'N' @{this.tryLogicallyDelete.prefix("t")} → t.deleted = 'N' @{this.tryLogicallyDelete.useWhereQuery} → where deleted = 'N' @{this.tryLogicallyDelete.useAndQuery} → and deleted = 'N' @{this.tryLogicallyDelete.useOrQuery} → or deleted = 'N' @{this.tryLogicallyDelete.useQueryValue} → or deleted = 'Y' @{this.tryLogicallyDelete.useDeletedValue} → or deleted = 'N' -- 关于乐观锁(需要在类上配置@Version) -- 没有配置相关注解的话,表达式返回一段空白文本("") -- @see com.viiyue.plugins.mybatis.template.builder.OptimisticLockBuilder @{this.tryOptimisticLock} → version = #{version} @{this.tryOptimisticLock.prefix("t")} → t.version = #{version} @{this.tryOptimisticLock.useWhere} → where version = #{version} @{this.tryOptimisticLock.useAnd} → and version = #{version} @{this.tryOptimisticLock.useOr} → or version = #{version} ``` > %{expression} - 动态模板 ```sql -- 关于列 -- $ 是当前传入的参数,如果单个参数,可以直接写 $ 符号,多参数使用 $.param 的形式。 -- 会筛选出Bean中所有non-null的属性,值得注意的是 @Column(nullable=true/false) -- @see com.viiyue.plugins.mybatis.template.builder.ColumnBuilder %{this.columns.dynamic($)} → id, name %{this.columns.dynamic($).include("id,name")} → id, name %{this.columns.dynamic($).exclude("id,age")} → name %{this.columns.dynamic($).prefix("t")} → t.id, t.name, t.age %{this.columns.dynamic($).prefix("t").include("id,name").exclude("id")} → t.name -- 关于修改 -- 注意:如果开启了乐观锁的话,版本字段的取值不再和字段名一样,类似:next(?)Value -- @see com.viiyue.plugins.mybatis.template.builder.UpdateSetBuilder %{this.set} → id = #{id}, name = #{name}, version = #{nextVersionValue} %{this.set.prefix("t")} → t.id = #{id}, t.name = #{name}, t.age = #{age} %{this.set.alias("user")} → id = #{user.id}, name = #{user.name}, age = #{user.age} %{this.set.include("id,name")} → id = #{id}, name = #{name} %{this.set.exclude("id,name")} → age = #{age} %{this.set.dynamic($)} → name = #{name} %{this.set.dynamic($.user).prefix("t").alias("user")} → t.name = #{user.name} -- 关于动态值 -- 构造器会自动筛选出所有non-null的属性,这里只是一个示例效果。 -- @see com.viiyue.plugins.mybatis.template.builder.ValuesBuilder %{this.values.dynamic($)} → #{id}, #{name}, #{age} %{this.values.dynamic($).alias("user")} → #{user.id}, #{user.name}, #{user.age} %{this.values.dynamic($).include("id,name")} → #{id}, #{name} %{this.values.dynamic($).exclude("id,age")} → #{name} %{this.values.dynamic($).alias("u").include("name,age")} → #{u.name}, #{u.age} -- 关于Where条件 -- 构造器会自动筛选出所有non-null的属性,这里只是一个示例效果。 -- @see com.viiyue.plugins.mybatis.template.builder.WhereBuilder %{this.where($)} → where name = #{name} and age = #{age} %{this.where($).prefix("t")} → where t.name = #{name} and t.age = #{age} %{this.where($).include("name")} → where name = #{name} %{this.where($).exclude("name")} → where age = #{age} %{this.where($).tryLogicallyDeleteQuery} → where deleted = 'Y' and name = #{name} %{this.where($).tryLogicallyDeleteQuery.useQueryValue} → where deleted = 'Y' and name = #{name} %{this.where($).tryLogicallyDeleteQuery.useDeletedValue} → where deleted = 'N' and name = #{name} ``` > [keywords] - 关键字转换 需要说明一下,如果不做偏好配置的话,插件默认全部转换为小写关键字,如果想使用大写关键字,请更改相关配置。 ```sql [select] * [from] t_user [where] name = #{name} -- enableKeywordsToUppercase = true SELECT * FROM t_user WHERE name = #{name} -- enableKeywordsToUppercase = false / default select * from t_user where name = #{name} ``` > {{expression}} - 取值表达式 这种表达式主要是 **Example** 查询的时候用的相对多一些,其他情况你要使用也是可以的。此表达式不输出任何修饰符,大家使用的话记得添加修饰符,比如:引号。 ```sql -- Example select {{$.example.columns}} from @{this.table} {{$.example.where}} -- 获取系统值,表达式具体的值在运行时生效 -- 目前{{system.xxx}}仅支持下面四个属性 update @{this.table} set modify_time = {{system.now}} where ... -- Date update @{this.table} set millis = {{system.systime}} where ... -- CurrentTimeMillis update @{this.table} set order_code = '{{system.uuid}}' where ... -- UUID update @{this.table} set sort_value = {{system.rundom.nexInt(5)}} where ... -- Number -- 获取环境变量值,表达式具体的值在运行时生效 -- 更多属性调用请参照以下常量类的ENV_PROP_NAMES属性值 -- @see com.viiyue.plugins.mybatis.Constants#ENV_PROP_NAMES insert into @{this.table} (name, text) values ('{{env.osName}', '{{env.osVersion}}') ``` > <error>message</error> - 异常表达式 这种情况不要轻易写在SQL脚本中,如果你写在了自己的SQL脚本中,执行方法时会把标签内部的文本信息以 `RuntimeException` 的形式抛出来,目前也只是插件内部用来判断一些特殊情况时才会使用到。 [回到顶部](#功能列表) ## 支持SQL注释 众所周知,XML文件中的SQL脚本是不支持注释的,但是我们可以帮你实现在XML添加脚本注释,你可以直接从DB软件中整个复制过来,而不需要单独剔除你添加的注释,不要惊慌,多余的注释会在你程序启动过程中被移除掉,不会有任何效率上的影响,所以放心拥抱SQL注释吧。 ```xml ``` [回到顶部](#功能列表) ## 支持各种主键生成策略 目前插件主要支持以下四种主键生成策略,使用 `@Id` 标识主键,然后使用 `@GeneratedKey` 对主键生成策略进行配置。 ```java // 省略各种注解配置 public class YouBean { @Id // 1、使用JDBC的自增主键获取方式 @GeneratedKey( useGeneratedKeys = true ) // 2、直接生成主键值,插件提供两种默认主键值生成器(SnowFlakeId/UUID) // @GeneratedKey( valueProvider = SnowFlakeIdValueProvider.class ) // @GeneratedKey( valueProvider = UUIDValuePrivoder.class ) // 3、对于不支持JDBC获取自增主键值的数据库来说,可以像下面这样使用: // 具体参照com.viiyue.plugins.mybatis.enums.AutoIncrement里面的枚举值, // 里面预置了部分获取自增主键的SQL,可以直接写枚举名字,没有的话也可以自己写SQL脚本。 // @GeneratedKey( statement = "MYSQL" ) // MYSQL是枚举名,通过枚举找到对应SQL脚本 // @GeneratedKey( statement = "SELECT T_USER.YYYY()" ) // 直接写SQL脚本 // 4、自定义自增主键SQL提供者 // 如果枚举里面没有你需要的,可以通过statementProvider来提供你自己的SQL主键查询 // @GeneratedKey( statementProvider = OracleAutoIncrementStatementProvider.class ) private Long id; } // 自定义自增主键SQL脚本 public class OracleAutoIncrementStatementProvider implements AutoIncrementStatementProvider { @Override public String getAutoIncrementSqlStatement( GeneratedKeyInfo info ) { return "SELECT " + info.getTableName() + ".NEXTVAL FROM DUAL"; } } ``` [回到顶部](#功能列表) ## 支持多主键场景 > Bean的定义 可以对多个主键字段进行 `@Id` 标注,没有特殊指明的话,默认会使用对象中第一个标注的主键,否则将会使用 `@Id(primary=true)` 的那一个主键。 ```java // 省略各种注解配置 public class YouBean { @Id private Long id; @Id(primary = true) private Long id2; } ``` > 使用上的区别 ```java mapper.selectByPrimaryKey(PK); // 使用默认主键 mapper.selectByPrimaryKeyIndex(Index, PK); // 使用指定下标的主键,多主键顺序由实体Bean决定 mapper.selectByPrimaryKeyGroup(Pk...); // 使用默认主键 mapper.selectByPrimaryKeyGroupIndex(Index, PK...); // 使用指定下标的主键,多主键顺序由实体Bean决定 ``` [回到顶部](#功能列表) ## 更方便快捷的条件查询 ```java Example example = null; // query // 方法后面可以直接跟各种Where条件 example = Example.query(User.class).equal("id", 1L).lt("age", 60).xxx(...); // select // 该方法可以对列进行操作,条件筛选的话使用when()来桥接 example = Example.select(User.class).includes( "id", "loginName", "password" ); example.when().equal("id", 1L).lt("age", 60).xxx(...); // update // 使用set/values可以对单个字段进行设值,不支持乐观锁 example = Example.update(User.class).set(xx, yy, zz).values(XX, YY, ZZ); example.when().equal("id", 1L).lt("age", 60).xxx(...); // update // 还可以绑定某个实体对象来修改 User user = null; Example.update(User.class).bind(user).when().equal("id", 1L).xxx(...); // 具体使用 mapper.selectByExample(example); mapper.updateByExample(example); mapper.deleteByExample(example); ``` [回到顶部](#功能列表) ## 支持聚合函数统计 ```java Example example = null; // 支持多字段统计,* 仅能在count函数中使用,其他函数使用会出现异常 example = Example.count(User.class, "*", ...); // 统计行数 example = Example.summation(User.class, "price", "num", ...); // 求和 example = Example.maximum(User.class, "price", "num", ...); // 求最大值 example = Example.minimum(User.class, "price", "num", ...); // 求最小值 example = Example.average(User.class, "price", "num", ...); // 求平均值 // 条件筛选 example.when().equal("id", 1L).lt("age", 60).xxx(); // 统计单个值,为了兼容不同的数据类型,统一使用BigDecimal接口,大家可自行转换成需要的数据类型 // 这种情况只能统计单列,如果统计多个字段,会出现SQL异常,此时请使用下面这种方式 BigDecimal result = mapper.selectStatisticByAggregateFunction(example); // 统计多列,返回的是对应的实体对象,统计的字段值会自动封装到对象同名字段中 List results = mapper.selectStatisticListByAggregateFunction(example); ``` [回到顶部](#功能列表) ## 支持数据库乐观锁 只需要在你的字段上标注 `@Version` 即可,**乐观锁注解只能出现一次**,默认为版本自增实现,数据类型支持 `Short`、`Integer`、`Long`、`Timestamp`,还可以选择雪花版本值,甚至你可以自己实现版本值的获取,实现 `NextVersionProvider` 接口即可。 ```java // 省略各种注解配置 public class User { @Version // 默认:DefaultNextVersionProvider.class // @Version(nextVersion = SnowFlakeIdNextVersionProvider.class) private Long version; } ``` [回到顶部](#功能列表) ## 支持各种逻辑删除 逻辑删除需要配合 `@LogicallyDelete` 注解一起使用,如无任何注解配置,方法执行将会抛出异常,**只可配置一次**。 ```java // 逻辑删除所有 mapper.logicallyDeleteAll(); // 根据特定条件逻辑删除部分 mapper.logicallyDelete(Object); // 通过主键逻辑删除指定数据 mapper.logicallyDeleteByPrimaryKey(PK); // 通过主键数组逻辑删除特定数据 mapper.logicallyDeleteByPrimaryKeyGroup(Pk...); // 多主键情况下,通过主键下标和主键值逻辑删除特定数据 mapper.logicallyDeleteByPrimaryKeyIndex(Integer, Pk); // 多主键情况下,通过主键下标和主键数组逻辑删除特定数据 mapper.logicallyDeleteByPrimaryKeyIndexGroup(Index, Pk...); // 通过自定义条件筛选逻辑删除特定数据 mapper.logicallyDeleteByExample(example); ``` [回到顶部](#功能列表) ## 支持逻辑删除数据的恢复 数据恢复也需要配合 `@LogicallyDelete` 注解一起使用,如无任何注解配置,方法执行将会抛出异常。 ```java // 查询所有被逻辑删除过的数据 mapper.selectAllDeleted(); // 根据特定条件还原指定数据 mapper.restore(Object); // 还原所有被逻辑删除过的数据 mapper.restoreAllDeleted(); // 通过主键还原指定Id的数据 mapper.restoreByPrimaryKey(Pk); // 通过主键数组批量还原数据 mapper.restoreByPrimaryKeyGroup(PK...); // 多主键的情况,通过指定主键下标和主键值还原特定数据 mapper.restoreByPrimaryKeyIndex(Integer, Pk); // 多主键的情况,通过指定主键下标和主键数组还原特定数据 mapper.restoreByPrimaryKeyIndexGroup(Index, Pk...); // 通过自定义条件筛选还原特定数据 mapper.restoreByExample(example); ``` [回到顶部](#功能列表) ## 支持查询自定义返回Bean类型 Mapper接口提供三个泛型参数,依次为<数据库实体类型,返回数据类型,主键类型>。对于返回数据类型你可以任意定义,但是 **ResultMap** 结果映射只会生成和 **数据库实体** 同名的匹配字段,其他不匹配的字段值将一直为 `null`。 ```java public class YourMapper extends Mapper { // 那么你的返回数据类型就是:UserDTO } ``` [回到顶部](#功能列表) ## 支持零MapperXML配置文件 因为插件通过Mybatis的注解 `@SelectProvider`、`@UpdateProvider`、`@InsertProvider`、`@DeleteProvider` 来提供基础 `SqlSource` ,所以即使你没有配置任何XML也是可以正常工作的。 [回到顶部](#功能列表) ## 扩展插件Api Mybatis提供的注解SQL功能本身就是一种扩展机制,所以扩展就很好理解了,你可以写自己的@xxxProvider,也可以在插件的基础上实现 `DynamicProvider` 进而扩展插件的Api,这样的话你就可以在通用的Mapper上调用你自己的Api了。 > 接口定义,需要继承Marker ```java public interface Mapper extends Marker { @SelectProvider( type = YourProvider.class, method = DynamicProvider.dynamicSQL ) List selectCustomApi( @Param("param1") String param1, @Param("param2") String param2 ); } ``` > 具体实现,需要继承DynamicProvider ```java public final class YourProvider extends DynamicProvider { public String selectCustomApi( MappedStatement ms ) { return "[select] @{this.columns} [from] @{this.table} [where] @{this.column.name} = #{param1} [and] @{this.column.xxx} = #{param2}"; } } ``` [回到顶部](#功能列表) ## 提供各种场景的日志打印 > 编译日志,需要开启 enableCompilationLog 配置 ``` ... -------------------------------------------------------------------------------- ... ----- Target: YourMapper( BaseSelectProvider ) ... -- Namespace: xxx.xxx.xxx.YourMapper.selectAll ... Template SQL: [select] @{this.columns} [from] @{this.table} @{this.tryLogicallyDelete.useWhereQuery} @{this.defaultOrderBy} ... Compiled SQL: SELECT `id`, `name`, `version` FROM `t_user` WHERE deleted = 'N' ORDER BY `id` DESC ... ------- Time: 1ms ... -------------------------------------------------------------------------------- ``` > 实时动态日志,需要开启 enableRuntimeLog 配置 ``` ... -------------------------------------------------------------------------------- ... ==> Compile runtime SQL ... ... -------------------------------------------------------------------------------- ... ==> - Template: SELECT `id`, `name`, `version` FROM `t_user` %{this.where($).tryLogicallyDeleteQuery} ORDER BY `id` DESC ... ==> - Compiled: SELECT `id`, `name`, `version` FROM `t_user` WHERE deleted = 'N' AND `name` = #{name} ORDER BY `id` DESC ... ==> Parameters: xxx.xxx.xxx.User@145eaa29 ... <== ----- Time: 7ms ... -------------------------------------------------------------------------------- ... ==> Preparing: SELECT `id`, `name`, `version` FROM `t_user` WHERE delete = 'N' AND `name` = ? ORDER BY `id` DESC ... ==> Parameters: xxx(String) ... <== Total: 3 ... -------------------------------------------------------------------------------- ``` [回到顶部](#功能列表) ## 关于作者 - 邮箱:[email protected] - 掘金: https://juejin.im/user/5da5621ce51d4524f007f35f - 简书: https://www.jianshu.com/u/e62f4302c51f - Issuse:https://github.com/tangxbai/mybatis-mapper/issues




© 2015 - 2024 Weber Informatics LLC | Privacy Policy