{"id":21900402,"url":"https://github.com/tangxbai/mybatis-mapper","last_synced_at":"2025-04-15T19:54:04.209Z","repository":{"id":35388818,"uuid":"213864262","full_name":"tangxbai/mybatis-mapper","owner":"tangxbai","description":"Mybatis generic mapper plugin for solving most basic operations, simplifying sql syntax and improving dynamic execution efficiency","archived":false,"fork":false,"pushed_at":"2023-03-24T07:12:43.000Z","size":430,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-15T19:53:58.524Z","etag":null,"topics":["java","mybatis","mybatis-mapper","sql-template"],"latest_commit_sha":null,"homepage":"https://github.com/tangxbai/mybatis-mapper","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tangxbai.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-09T08:33:46.000Z","updated_at":"2024-02-26T12:22:51.000Z","dependencies_parsed_at":"2022-09-10T23:41:06.459Z","dependency_job_id":null,"html_url":"https://github.com/tangxbai/mybatis-mapper","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangxbai%2Fmybatis-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangxbai%2Fmybatis-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangxbai%2Fmybatis-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangxbai%2Fmybatis-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tangxbai","download_url":"https://codeload.github.com/tangxbai/mybatis-mapper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249145296,"owners_count":21219966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","mybatis","mybatis-mapper","sql-template"],"created_at":"2024-11-28T15:08:04.001Z","updated_at":"2025-04-15T19:54:04.162Z","avatar_url":"https://github.com/tangxbai.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\r\n\r\n![MybatisMapper](mybatis-mapper-logo.png)\r\n\r\n[![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)\r\n\r\n\r\n\r\n## 项目简介\r\n\r\nMybatis通用Mapper插件，用于解决大多数基础CRUD，简化sql语法并提高动态执行效率，拥有更丰富的Api。用最少的配置，提供一个健全的使用体系。\r\n\r\n*注意：此项目是一款完全开源的项目，您可以在任何适用的场景使用它，商用或者学习都可以，如果您有任何项目上的疑问，可以在issue上提出您问题，我会在第一时间回复您，如果您觉得它对您有些许帮助，希望能留下一个您的星星（★），谢谢。*\r\n\r\n------\r\n\r\n此项目遵照 [Apache 2.0 License]( http://www.apache.org/licenses/LICENSE-2.0.txt ) 开源许可 \r\n\r\n技术讨论QQ群：947460272\r\n\r\n\r\n\r\n## 核心亮点\r\n\r\n- **无侵入**：100%兼容mybatis，不与mybatis冲突，只添加功能，对现有程序无任何影响；\r\n- **配置少**：所有配置均在原始mybatis的基础上读取，不增加额外配置消耗；\r\n- **无捆绑关系**：与XML文件独立，有无独立XML均可；\r\n- **效率高**：由Xml+OGNL模式转向Java+ExpressionEngine的模式，省去了XML的解析和OGNL解析的时间消耗；\r\n- **灵活的规则制定**：灵活多元化的（表/列）规则制定，完美融合各种（名字/类型等）不统一的场景；\r\n- **SQL模板语法**：模板语法简单易掌握，一次开发，终生受用，避免因数据库变化而大量更改SQL语句的场景。表达式会在程序完全启动之前编译成完整的SQL，仅留下需要动态解析的表达式，对效率的影响微乎甚微；\r\n- **CRUD增强**：除了提供基础的CRUD外还提供一系列高级辅助方法（Example/ForUpdate/聚合函数/逻辑删除/回收站/乐观锁等）；\r\n- **便捷的条件查询**：更简单便捷的Example条件查询，提供符合SQL语义化的链式条件函数调用；\r\n- **支持多主键**：支持多主键场景，CRUD中可选择特定主键进行操作；\r\n- **丰富的主键生成策略**：支持JDBC自增主键、自定义主键SQL查询、雪花ID、UUID、自定义主键生成策略等；\r\n- **支持常量值**：灵活化的常量值生成策略，可针对不同场景做不同操作，均支持雪花ID/UUID等内置生成器；\r\n- **可排序字段**：可对SQL字段排列顺序进行干扰，简直是强迫症重度患者的福音啊；\r\n- **粘连性小**：可以独立使用，纯Java环境/spring/springboot都提供了单独的组件。\r\n- **可扩展的开发模式**：继承Marker/Mapper/BaseMapper即可继续增强基础CRUD。\r\n\r\n\r\n\r\n## 关联文档\r\n\r\n关于整合spring，请移步到：https://github.com/tangxbai/mybatis-mapper-spring\r\n\r\n关于整合springboot，请移步到：https://github.com/tangxbai/mybatis-mapper-spring-boot\r\n\r\n\r\n\r\n## 项目演示\r\n\r\n- java + mybatis-mapper - [点击获取](https://github.com/tangxbai/mybatis-mapper-demo)\r\n- spring + mybatis-mapper - [点击获取](https://github.com/tangxbai/mybatis-mapper-spring-demo)\r\n- springboot + mybatis-mapper - [点击获取](https://github.com/tangxbai/mybatis-mapper-spring-boot/tree/master/mybatis-mapper-spring-boot-samples)\r\n\r\n\r\n\r\n## 功能列表\r\n\r\n- [支持模板语法](#支持模板语法)\r\n- [支持SQL注释](#支持SQL注释)\r\n- [支持各种主键生成策略](#支持各种主键生成策略)\r\n- [支持多主键场景](#支持多主键场景)\r\n- [更方便快捷的条件查询](#更方便快捷的条件查询)\r\n- [支持聚合函数统计](#支持聚合函数统计)\r\n- [支持数据库乐观锁](#支持数据库乐观锁)\r\n- [支持各种逻辑删除](#支持各种逻辑删除)\r\n- [支持逻辑删除数据的恢复](#支持逻辑删除数据的恢复)\r\n- [支持查询自定义返回Bean类型](#支持查询自定义返回Bean类型)\r\n- [支持零MapperXML配置文件](#支持零MapperXML配置文件)\r\n- [扩展插件Api](#扩展插件Api)\r\n- [提供各种场景的日志打印](#提供各种场景的日志打印)\r\n- 提供更丰富的API\r\n\r\n\r\n\r\n## 快速开始\r\n\r\nMaven方式（**推荐**）\r\n\r\n```xml\r\n\u003cdependency\u003e\r\n\t\u003cgroupId\u003ecom.viiyue.plugins\u003c/groupId\u003e\r\n\t\u003cartifactId\u003emybatis-mapper\u003c/artifactId\u003e\r\n\t\u003cversion\u003e[VERSION]\u003c/version\u003e\r\n\u003c/dependency\u003e\r\n```\r\n\r\n如果你没有使用Maven构建工具，那么可以通过以下途径下载相关jar包，并导入到你的编辑器。\r\n\r\n[点击跳转下载页面](https://search.maven.org/search?q=g:com.viiyue.plugins%20AND%20a:mybatis-mapper\u0026core=gav)\r\n\r\n![如何下载](https://user-gold-cdn.xitu.io/2019/10/16/16dd24a506f37022?w=995\u0026h=126\u0026f=png\u0026s=14645)\r\n\r\n如何获取最新版本？[点击这里获取最新版本](https://search.maven.org/search?q=g:com.viiyue.plugins%20AND%20a:mybatis-mapper\u0026core=gav)\r\n\r\n\r\n\r\n## 如何使用\r\n\r\n1、配置 mybatis.xml\r\n\r\n这个文件具体如何配置不作过多说明，你可以拉取相关demo查看详细配置，在配置上也没有什么区别，需要注意的是 **typeAliases**（实体别名配置）一定要配置，不然插件可能无法正常工作。\r\n\r\n2、配置数据库实体Bean\r\n\r\n```java\r\n@Table( prefix = \"t_\" ) // 表名生成规则，可以配置更多详细说明\r\n@NamingRule( NameStyle.UNDERLINE ) // 字段和数据库列之间的转换规则\r\n@ValueRule( ValueStyle.SHORT ) // 值的生成规则，类似于：#{id}\r\n@ExpressionRule( ExpressionStyle.SHORT ) // 表达式生成规则，类似于: id = #{id}\r\n@DefaultOrderBy( \"#pk\" ) // #默认排序字段，\"pk\"为主键占位符，指向当前生效的主键字段，也可以直接写\"id\"\r\npublic class YourModelBean {\r\n\r\n    @Id // 主键可以配置多个，但是只会有一个生效，Api方法中如果想要使用其他主键请指明所在下标位置\r\n    @Index( Integer.MIN_VALUE )\r\n    @GeneratedKey( useGeneratedKeys = true ) // JDBC支持的自增主键获取方式\r\n    // @GeneratedKey( valueProvider = SnowFlakeIdValueProvider.class ) // 雪花Id，插件提供的两种主键生成策略之一\r\n    // @GeneratedKey( statement = \"MYSQL\" ) // 枚举引用\r\n    // @GeneratedKey( statement = \"SELECT LAST_INSERT_ID()\" ) // 自增主键SQL查询语句\r\n    // @GeneratedKey( statementProvider = YourCustomStatementProvider.class ) // 通过Provider提供SQL语句\r\n    private Long id;\r\n\r\n    @Index( Integer.MAX_VALUE - 4 )\r\n    @Column( jdcbType = Type.CHAR ) // 对字段进行详细描述\r\n    @LogicallyDelete( selectValue = \"Y\", deletedValue = \"N\" ) // 开启逻辑删除支持，只能配置一次\r\n    private Boolean display;\r\n\r\n    @Index( Integer.MAX_VALUE - 3 )\r\n    private Date createTime;\r\n\r\n    @Index( Integer.MAX_VALUE - 2 )\r\n    private Date modifyTime;\r\n\r\n    @Version // 开启乐观锁支持，只能配置一次\r\n    @Index( Integer.MAX_VALUE - 1 )\r\n    @Column( insertable = false )\r\n    private Long version;\r\n    \r\n    // setter/getter...\r\n    \r\n    // ----------------------------------------------------------------\r\n    // @Index主要对字段出现顺序进行干扰，对字段进行干扰以后，输出的顺序大概是这样：\r\n    // =\u003e id, ..., display, create_time, modify_time, version\r\n    // 如果您未使用@Index注解，那么字段的原始顺序是这样的：\r\n    // =\u003e id, display, create_time, modify_time, version, ...\r\n    // 默认输出会将父类的字段排在最前面\r\n    // ----------------------------------------------------------------  \r\n\r\n}\r\n```\r\n\r\n3、Mapper接口需要继承 `BaseMapper` 或者 `Mapper`\r\n\r\n```java\r\n// 继承Mapper\r\npublic interface YourMapper extends Mapper\u003cYourModelBean, YourModelBeanDTO, Long\u003e {\r\n}\r\n// 或者继承BaseMapper\r\npublic interface YourMapper extends BaseMapper\u003cYourModelBean, YourModelBeanDTO, Long\u003e {\r\n}\r\n```\r\n\r\n4、使用方式\r\n\r\n```java\r\nSqlSessionFactory factory = new MyBatisMapperFactoryBuilder().build( Resources.getResourceAsStream(\"your-mybatis.xml\"));\r\nSqlSession session = factory.openSession();\r\nYourMapper mapper = session.getMapper(YourMapper.class);\r\nmapper.xxx(...);\r\nsession.commit();\r\n```\r\n\r\n请注意：**MyBatisMapperFactoryBuilder** 是插件提供的一个 **SqlSessionFactory** 工厂构造器，这里我们需要用插件提供的MyBatisMapperFactoryBuilder替换mybatis原始的 **SqlSessionFactoryBuilder** 以启用插件相关Api功能。\r\n\r\n\r\n\r\n## 配置注解\r\n\r\n\u003ctable\u003e\r\n    \u003cthead\u003e\r\n    \t\u003ctr\u003e\r\n        \t\u003cth align=\"left\"\u003e类型\u003c/th\u003e\r\n            \u003cth align=\"left\"\u003e注解\u003c/th\u003e\r\n            \u003cth align=\"left\"\u003e描述\u003c/th\u003e\r\n        \u003c/tr\u003e\r\n    \u003c/thead\u003e\r\n    \u003ctbody\u003e\r\n    \t\u003ctr\u003e\r\n        \t\u003ctd rowspan=\"4\"\u003e类注解\u003c/td\u003e\r\n            \u003ctd\u003e@Table\u003c/td\u003e\r\n            \u003ctd\u003e配置表名生成规则\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@ResultMap\u003c/td\u003e\r\n            \u003ctd\u003e自定义ResultMap，默认使用\u003ccode\u003eBaseResultMap\u003c/code\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@Excludes\u003c/td\u003e\r\n            \u003ctd\u003e排除不需要的字段属性，一般用于子类排除父类某字段的场景\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@DefaultOrderBy\u003c/td\u003e\r\n            \u003ctd\u003e默认排序字段，\u003ccode\u003e#pk\u003c/code\u003e内置占位符，隐式地指向当前生效的主键\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n         \u003ctr\u003e\r\n        \t\u003ctd rowspan=\"3\"\u003e规则注解\u003c/td\u003e\r\n            \u003ctd\u003e@NamingRule\u003c/td\u003e\r\n            \u003ctd\u003e配置字段名和数据库列的转换规则\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@ValueRule\u003c/td\u003e\r\n            \u003ctd\u003e配置值的生成规则，类似：\u003ccode\u003e#{id, ...}\u003c/code\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@ExpressionRule\u003c/td\u003e\r\n            \u003ctd\u003e配置表达式的生成规则，类似：\u003ccode\u003eid = #{id, ...}\u003c/code\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd colspan=\"3\"\u003e以上两种类型的注解都只能配置在类上，主要用于描述数据库实体Bean的一些基础信息，通常建议配置在父类上，进而避免大量重复代码的产生。\u003c/td\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd rowspan=\"8\"\u003e成员注解\u003c/td\u003e\r\n        \t\u003ctd\u003e@Id\u003c/td\u003e\r\n            \u003ctd\u003e主键标识，默认使用第一个标注字段，否则使用\u003ccode\u003eprimary\u003c/code\u003e为true的字段作为主键\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@Index\u003c/td\u003e\r\n            \u003ctd\u003e干扰字段的排列顺序，默认按照Bean定义的顺序从父类到子类排列\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@Column\u003c/td\u003e\r\n            \u003ctd\u003e显式地配置字段和数据库列的规则说明\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@GeneratedKey\u003c/td\u003e\r\n            \u003ctd\u003e主键生成策略，必须和\u003ccode\u003e@Id\u003c/code\u003e组合使用，否则无效，\u003cb\u003e且只能出现一次\u003c/b\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@GeneratedValue\u003c/td\u003e\r\n            \u003ctd\u003e生成常量值，插件提供 SnowFlakeId/UUID，可自行拓展\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@Conditional\u003c/td\u003e\r\n            \u003ctd\u003e条件表达式，默认使用 \u003ccode\u003e=\u003c/code\u003e 桥接前后条件，可更改条件规则\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@LogicallyDelete\u003c/td\u003e\r\n            \u003ctd\u003e启用逻辑删除，\u003cb\u003e只能出现一次\u003c/b\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@Version\u003c/td\u003e\r\n            \u003ctd\u003e启用乐观锁，\u003cb\u003e只能出现一次\u003c/b\u003e\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd colspan=\"3\"\u003e成员注解主要是对实体字段的一些描述\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd rowspan=\"2\"\u003e标识注解\u003c/td\u003e\r\n        \t\u003ctd\u003e@EnableResultMap\u003c/td\u003e\r\n            \u003ctd\u003e标注在Mapper方法上，是否使用ResultMap结果映射\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd\u003e@Reference\u003c/td\u003e\r\n            \u003ctd\u003e标注在Mapper方法上，指向@XXXProvider(type)的其他非同名方法\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n        \t\u003ctd colspan=\"3\"\u003e标识注解主要用于扩展插件Api的时候用的场景多一些，你也可以在自己的Mapper上使用默认的ResultMap，申明一下即可。\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n    \u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\r\n\r\n\r\n## 偏好配置\r\n\r\n\u003e 属性说明\r\n\r\n\u003ctable\u003e\r\n    \u003cthead\u003e\r\n    \t\u003ctr\u003e\r\n            \u003cth width=\"20%\" align=\"left\"\u003e属性\u003c/th\u003e\r\n            \u003cth width=\"50%\" align=\"left\"\u003e描述\u003c/th\u003e\r\n            \u003cth width=\"15%\" align=\"left\"\u003e类型\u003c/th\u003e\r\n            \u003cth width=\"15%\" align=\"left\"\u003e默认\u003c/th\u003e\r\n        \u003c/tr\u003e\r\n    \u003c/thead\u003e\r\n    \u003ctbody\u003e\r\n    \t\u003ctr\u003e\r\n            \u003ctd\u003eenableLogger\u003c/td\u003e\r\n            \u003ctd\u003e是否启用日志\u003c/td\u003e\r\n            \u003ctd\u003eBoolean\u003c/td\u003e\r\n            \u003ctd\u003etrue\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003eenableMapperScanLog\u003c/td\u003e\r\n            \u003ctd\u003e是否开启Mapper扫描日志\u003c/td\u003e\r\n            \u003ctd\u003eBoolean\u003c/td\u003e\r\n            \u003ctd\u003etrue\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003eenableRuntimeLog\u003c/td\u003e\r\n            \u003ctd\u003e是否开启实时日志\u003c/td\u003e\r\n            \u003ctd\u003eBoolean\u003c/td\u003e\r\n            \u003ctd\u003etrue\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003eenableCompilationLog\u003c/td\u003e\r\n            \u003ctd\u003e是否开启编译日志\u003c/td\u003e\r\n            \u003ctd\u003eBoolean\u003c/td\u003e\r\n            \u003ctd\u003etrue\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003eenableKeywordsToUppercase\u003c/td\u003e\r\n            \u003ctd\u003e关键字大小写转换\u003c/td\u003e\r\n            \u003ctd\u003eBoolean\u003c/td\u003e\r\n            \u003ctd\u003efalse\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n        \u003ctr\u003e\r\n            \u003ctd\u003edatabaseColumnStyle\u003c/td\u003e\r\n            \u003ctd\u003e数据库列样式\u003c/td\u003e\r\n            \u003ctd\u003eString\u003c/td\u003e\r\n            \u003ctd\u003e#\u003c/td\u003e\r\n        \u003c/tr\u003e\r\n    \u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\r\n*特别说明*：`#` 是一个占位符，代表据数据库中的列名，比如mysql中默认列使用 \u0026#x60;column\u0026#x60;，那么你可以这样配置 \u0026#x60;#\u0026#x60;，默认是没有任何样式修饰符的。\r\n\r\n```sql\r\n-- 默认样式 - #\r\nselect id, name, age, weight from ... where ...\r\n-- Mysql样式 - `#`\r\nselect `id`, `name`, `age`, `weight` from ... where ...\r\n-- Oracle - [#]\r\nselect [id], [name], [age], [weight] from ... where ...\r\n-- 自定义样式 - L-#-R\r\nselect L-id-R, L-name-R, L-age-R, L-weight-R from ... where ...\r\n```\r\n\r\n\u003e 配置方式\r\n\r\n```xml\r\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\r\n\u003cconfiguration\u003e\r\n    \u003cproperties resource=\"jdbc.properties\"\u003e\r\n        \u003cproperty name=\"enableLogger\" value=\"true\"/\u003e\r\n        \u003cproperty name=\"enableRuntimeLog\" value=\"true\"/\u003e\r\n        \u003cproperty name=\"enableCompilationLog\" value=\"true\"/\u003e\r\n        \u003cproperty name=\"enableMapperScanLog\" value=\"true\"/\u003e\r\n        \u003cproperty name=\"enableKeywordsToUppercase\" value=\"true\"/\u003e\r\n        \u003cproperty name=\"databaseColumnStyle\" value=\"`#`\"/\u003e\r\n    \u003c/properties\u003e\r\n\u003c/configuration\u003e\r\n```\r\n\r\n\r\n\r\n## 支持模板语法\r\n\r\n以下是目前已经支持的模板语法，你可以在自定义 `DynamicProvider` 中无条件的使用它们，也可以开启XML模板语法支持并使用它。\r\n\r\n- `@{expression}` - 静态模板，会在程序启动过程中被解析成完整的文本。\r\n- `%{expression}` - 动态模板，会在SQL执行过程被解析成完整的文本，类似mybatis判断条件。\r\n- `[kewords]` - 关键字模板，会根据配置自动转换成大写或小写关键字。\r\n- `{{value.expression}}` - 取值表达式，可以获取执行方法的传入参数或程序上下文数据。\r\n- `\u003cerror\u003emessage\u003c/error\u003e` - 错误信息，用于隐藏错误信息，不影响程序启动，但会在执行过程中抛出。\r\n\r\n\u003e 关于this关键字\r\n\r\n可能你会在模板看到 `this` 字样的关键字，这个关键字默认指向当前Mapper对应的数据库Bean的 **解析对象**，如果你想在模板语法中使用其他Bean解析对象的话，请使用Mybatis提供的 **类对象别名** 进行调用，这将会类似于 @{this.table} 或者 @{user.table}/@{role.table}/@{xxx.table} 等。\r\n\r\n```java\r\nthis = EntityParser.getEntity(Bean.class);\r\n```\r\n\r\n\u003e 特别说明\r\n\r\n首先，插件分两部分，**默认是不支持XML模板语法解析的**，所以可以根据个人喜好，选择开启或者不使用它，插件的运行和XML没太大关系，基础功能是基于Mybatis内部的 `@SelectProvider`、`@UpdateProvider`、`@InsertProvider`、`@DeleteProvider` 注解提供运行所需的 `SqlSource`，所以即使无任何XML文件也可正常工作，因为都是对单表的扩展Api，所以如果涉及一些任何复杂SQL，请添加XML文件并书写自己的SQL逻辑脚本。\r\n\r\n\u003e 开启XML模板语法\r\n\r\n如果你需要在XML也使用这些模板语法，请配置解析XML的扩展 `LanguageDriver`，插件提供的扩展Driver是 `MyBatisMapperLanguageDriver`，Mybatis的LanguageDriver接口无任何限制，任何人都可以对其进行自定义更改，属于Mybatis的一种扩展机制，具体使用的话，可以在单个XML语句节点上配置 `lang` 属性来开启单个Statement支持，也可以覆盖Mybatis的默认 `XMLLanguageDriver` 解析驱动。\r\n\r\n1、单个语句块，使用lang属性即可\r\n\r\n```xml\r\n\u003cselect id=\"xxx\" lang=\"com.viiyue.plugins.mybatis.MyBatisMapperLanguageDriver\"\u003e\r\n    [select] @{this.columns} \r\n    [from] @{this.table} \r\n    [where] @{this.column.yourFieldName} = #{yourFieldName}\r\n\u003c/select\u003e\r\n```\r\n\r\n2、全局范围，需要覆盖mybatis默认语言驱动\r\n\r\n```xml\r\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\r\n\u003cconfiguration\u003e\r\n    \u003csettings\u003e\r\n        \u003csetting name=\"defaultScriptingLanguage\" value=\"com.viiyue.plugins.mybatis.MyBatisMapperLanguageDriver\"/\u003e\r\n    \u003c/settings\u003e\r\n\u003c/configuration\u003e\r\n```\r\n\r\n3、DynamicProvider无条件支持任何模板语法\r\n\r\n```java\r\npublic final class YourCustomProvider extends DynamicProvider {\r\n    // 实现一\r\n    // 方法名必须和你接口中定义的方法名一致\r\n    public String selectAll( MappedStatement ms ) {\r\n        return \"[select] @{this.columns} [from] @{this.table}\";\r\n    }\r\n    \r\n    // 实现二\r\n    // 两个参数，第二个为当前对应的Mapper数据库实体Class类型\r\n    public String selectAll( MappedStatement ms, Class\u003c?\u003e yourModelBeanType ) {\r\n        System.out.println(yourModelBeanType);\r\n        return \"[select] @{this.columns} [from] @{this.table}\";\r\n    }\r\n}\r\n```\r\n\r\n接下来对每一种模板语法作一些详细说明，方便大家能更好的理解并熟练的使用它们。现在假设当前Mapper是下面这样的，那么 `this` 关键字会指向 **User的解析对象**，将从其中获取各种元数据信息。\r\n\r\n```java\r\n// DO\r\n// 省略各种注解配置\r\npublic class User {\r\n    private Long id;\r\n    private String name;\r\n    private Integer age;\r\n}\r\n\r\n// Mapper\r\npublic interface UserMapper extends Mapper\u003cUser, UserDTO, Long\u003e { \r\n}\r\n\r\n// DO → User\r\n// DTO → UserDTO\r\n// PK → Long\r\n// this → EntityParser.getEntity(User.class);\r\n```\r\n\r\n\u003e @{expression} - 静态模板\r\n\r\n```sql\r\n-- 关于表\r\n-- @see com.viiyue.plugins.mybatis.template.builder.TableBuilder\r\n@{this.table} → t_user\r\n@{this.table.prefix(\"xxx\")} → xxx.t_user\r\n@{this.table.alias(\"t\")} → t_user as 't'\r\n@{this.table.prefix(\"xxx\").alias(\"t\")} → xxx.t_user as 't'\r\n\r\n-- 关于单列\r\n-- @see com.viiyue.plugins.mybatis.template.builder.ColumnBuilder\r\n@{this.column.yourFieldName} → your_field_name\r\n@{this.column.yourFieldName.prefix(\"a\")} → a.your_field_name\r\n@{this.column.yourFieldName.suffix(\"_suffix\")} → your_field_name_suffix\r\n@{this.column.yourFieldName.javaType} → Integer/Long/YourFieldType\r\n@{this.column.yourFieldName.jdbcType} → INT/BIGINT/OTHERS\r\n@{this.column.yourFieldName.property} → yourFieldName\r\n@{this.column.yourFieldName.prefix(\"a\").suffix(\"_suffix\")} → a.your_field_name_suffix\r\n\r\n-- 关于所有列\r\n-- @see com.viiyue.plugins.mybatis.template.builder.ColumnsBuilder\r\n@{this.columns} → id, name, age\r\n@{this.columns.include(\"id,name\")} → id, name\r\n@{this.columns.exclude(\"id,age\")} → name\r\n@{this.columns.prefix(\"t\")} → t.id, t.name, t.age\r\n@{this.columns.prefix(\"t\").include(\"id,name\").exclude(\"id\")} → t.name\r\n\r\n-- 关于值\r\n-- @see com.viiyue.plugins.mybatis.template.builder.ValuesBuilder\r\n@{this.values} → #{id}, #{name}, #{age}\r\n@{this.values.alias(\"user\")} → #{user.id}, #{user.name}, #{user.age}\r\n@{this.values.include(\"id,name\")} → #{id}, #{name}\r\n@{this.values.exclude(\"id,age\")} → #{name}\r\n@{this.values.alias(\"user\").include(\"name,age\")} → #{user.name}, #{user.age}\r\n\r\n-- 关于默认排序（需要在类上配置@DefaultOrderBy）\r\n-- 没有配置相关注解的话，表达式返回一段空白文本(\"\")\r\n-- @see com.viiyue.plugins.mybatis.template.builder.LogicallyDeleteBuilder\r\n@{this.defaultOrderBy} → order by sorter desc\r\n@{this.defaultOrderBy.desc} → order by sorter desc\r\n@{this.defaultOrderBy.asc} → order by sorter asc\r\n@{this.defaultOrderBy.prefix(\"t\")} → order by t.sorter desc\r\n\r\n-- 关于逻辑删除（需要在字段上配置@LogicallyDelete）\r\n-- 没有配置相关注解的话，表达式返回一段空白文本(\"\")\r\n-- @see com.viiyue.plugins.mybatis.template.builder.LogicallyDeleteBuilder\r\n@{this.tryLogicallyDelete} → deleted = 'N'\r\n@{this.tryLogicallyDelete.prefix(\"t\")} → t.deleted = 'N'\r\n@{this.tryLogicallyDelete.useWhereQuery} → where deleted = 'N'\r\n@{this.tryLogicallyDelete.useAndQuery} → and deleted = 'N'\r\n@{this.tryLogicallyDelete.useOrQuery} → or deleted = 'N'\r\n@{this.tryLogicallyDelete.useQueryValue} → or deleted = 'Y'\r\n@{this.tryLogicallyDelete.useDeletedValue} → or deleted = 'N'\r\n\r\n-- 关于乐观锁（需要在类上配置@Version）\r\n-- 没有配置相关注解的话，表达式返回一段空白文本(\"\")\r\n-- @see com.viiyue.plugins.mybatis.template.builder.OptimisticLockBuilder\r\n@{this.tryOptimisticLock} → version = #{version}\r\n@{this.tryOptimisticLock.prefix(\"t\")} → t.version = #{version}\r\n@{this.tryOptimisticLock.useWhere} → where version = #{version}\r\n@{this.tryOptimisticLock.useAnd} → and version = #{version}\r\n@{this.tryOptimisticLock.useOr} → or version = #{version}\r\n```\r\n\r\n\u003e %{expression} - 动态模板\r\n\r\n```sql\r\n-- 关于列\r\n-- $ 是当前传入的参数，如果单个参数，可以直接写 $ 符号，多参数使用 $.param 的形式。\r\n-- 会筛选出Bean中所有non-null的属性，值得注意的是 @Column(nullable=true/false)\r\n-- @see com.viiyue.plugins.mybatis.template.builder.ColumnBuilder\r\n%{this.columns.dynamic($)} → id, name\r\n%{this.columns.dynamic($).include(\"id,name\")} → id, name\r\n%{this.columns.dynamic($).exclude(\"id,age\")} → name\r\n%{this.columns.dynamic($).prefix(\"t\")} → t.id, t.name, t.age\r\n%{this.columns.dynamic($).prefix(\"t\").include(\"id,name\").exclude(\"id\")} → t.name\r\n\r\n-- 关于修改\r\n-- 注意：如果开启了乐观锁的话，版本字段的取值不再和字段名一样，类似：next(?)Value\r\n-- @see com.viiyue.plugins.mybatis.template.builder.UpdateSetBuilder\r\n%{this.set} → id = #{id}, name = #{name}, version = #{nextVersionValue}\r\n%{this.set.prefix(\"t\")} → t.id = #{id}, t.name = #{name}, t.age = #{age}\r\n%{this.set.alias(\"user\")} → id = #{user.id}, name = #{user.name}, age = #{user.age}\r\n%{this.set.include(\"id,name\")} → id = #{id}, name = #{name}\r\n%{this.set.exclude(\"id,name\")} → age = #{age}\r\n%{this.set.dynamic($)} → name = #{name}\r\n%{this.set.dynamic($.user).prefix(\"t\").alias(\"user\")} → t.name = #{user.name}\r\n\r\n-- 关于动态值\r\n-- 构造器会自动筛选出所有non-null的属性，这里只是一个示例效果。\r\n-- @see com.viiyue.plugins.mybatis.template.builder.ValuesBuilder\r\n%{this.values.dynamic($)} → #{id}, #{name}, #{age}\r\n%{this.values.dynamic($).alias(\"user\")} → #{user.id}, #{user.name}, #{user.age}\r\n%{this.values.dynamic($).include(\"id,name\")} → #{id}, #{name}\r\n%{this.values.dynamic($).exclude(\"id,age\")} → #{name}\r\n%{this.values.dynamic($).alias(\"u\").include(\"name,age\")} → #{u.name}, #{u.age}\r\n\r\n-- 关于Where条件\r\n-- 构造器会自动筛选出所有non-null的属性，这里只是一个示例效果。\r\n-- @see com.viiyue.plugins.mybatis.template.builder.WhereBuilder\r\n%{this.where($)} → where name = #{name} and age = #{age}\r\n%{this.where($).prefix(\"t\")} → where t.name = #{name} and t.age = #{age}\r\n%{this.where($).include(\"name\")} → where name = #{name}\r\n%{this.where($).exclude(\"name\")} → where age = #{age}\r\n%{this.where($).tryLogicallyDeleteQuery} → where deleted = 'Y' and name = #{name}\r\n%{this.where($).tryLogicallyDeleteQuery.useQueryValue} → where deleted = 'Y' and name = #{name}\r\n%{this.where($).tryLogicallyDeleteQuery.useDeletedValue} → where deleted = 'N' and name = #{name}\r\n```\r\n\r\n\u003e [keywords] - 关键字转换\r\n\r\n需要说明一下，如果不做偏好配置的话，插件默认全部转换为小写关键字，如果想使用大写关键字，请更改相关配置。\r\n\r\n```sql\r\n[select] * [from] t_user [where] name = #{name}\r\n-- enableKeywordsToUppercase = true\r\nSELECT * FROM t_user WHERE name = #{name}\r\n-- enableKeywordsToUppercase = false / default\r\nselect * from t_user where name = #{name}\r\n```\r\n\r\n\u003e {{expression}} - 取值表达式\r\n\r\n这种表达式主要是 **Example** 查询的时候用的相对多一些，其他情况你要使用也是可以的。此表达式不输出任何修饰符，大家使用的话记得添加修饰符，比如：引号。\r\n\r\n```sql\r\n-- Example\r\nselect {{$.example.columns}} from @{this.table} {{$.example.where}}\r\n\r\n-- 获取系统值，表达式具体的值在运行时生效\r\n-- 目前{{system.xxx}}仅支持下面四个属性\r\nupdate @{this.table} set modify_time = {{system.now}} where ... -- Date\r\nupdate @{this.table} set millis = {{system.systime}} where ... -- CurrentTimeMillis\r\nupdate @{this.table} set order_code = '{{system.uuid}}' where ... -- UUID\r\nupdate @{this.table} set sort_value = {{system.rundom.nexInt(5)}} where ... -- Number\r\n\r\n-- 获取环境变量值，表达式具体的值在运行时生效\r\n-- 更多属性调用请参照以下常量类的ENV_PROP_NAMES属性值\r\n-- @see com.viiyue.plugins.mybatis.Constants#ENV_PROP_NAMES\r\ninsert into @{this.table} (name, text) values ('{{env.osName}', '{{env.osVersion}}')\r\n```\r\n\r\n\u003e  \u0026lt;error\u0026gt;message\u0026lt;/error\u0026gt;  - 异常表达式\r\n\r\n这种情况不要轻易写在SQL脚本中，如果你写在了自己的SQL脚本中，执行方法时会把标签内部的文本信息以 `RuntimeException` 的形式抛出来，目前也只是插件内部用来判断一些特殊情况时才会使用到。\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持SQL注释\r\n\r\n众所周知，XML文件中的SQL脚本是不支持注释的，但是我们可以帮你实现在XML添加脚本注释，你可以直接从DB软件中整个复制过来，而不需要单独剔除你添加的注释，不要惊慌，多余的注释会在你程序启动过程中被移除掉，不会有任何效率上的影响，所以放心拥抱SQL注释吧。\r\n\r\n```xml\r\n\u003cselect id=\"xxx\" resultMap=\"xxx\"\u003e\r\n    // 单行注释\r\n    // 支持大小写关键字转换，凡是包裹在“[]”中的任何文本，都会被转换成全大写或全小写文本。\r\n    [select]\r\n\r\n    -- SQL注释\r\n    -- 输出表的所有列\r\n    -- 注意：注释不支持#注释，#会和mybatis的取值表达式冲突，所以不要使用#注释\r\n    @{this.columns}\r\n    [from]\r\n\r\n    /* 单行文本注释 */\r\n    /* 输出表名 */\r\n    @{this.table} /* --- [where] --- */\r\n\r\n    /**\r\n     * 多行文本注释多行文本注释\r\n     * 多行文本注释多行文本注释\r\n     * 多行文本注释多行文本注释\r\n     * 多行文本注释多行文本注释\r\n     */\r\n\r\n    // 所有程序通用的单行注释也是支持的\r\n    // 内容可以直接写表达式，也可以结合mybatis的逻辑标签，没有任何限制。\r\n    // @{this.column.loginName} = #{loginName}\r\n\r\n    // 可以结合各种条件标签使用模板语法\r\n    \u003ctrim prefix=\"[where]\" prefixOverrides=\"and|AND\"\u003e\r\n        \u003cif test=\"loginName != null\"\u003e[and] @{this.column.xxx} = #{xxx}\u003c/if\u003e\r\n    \u003c/trim\u003e\r\n\r\n    \u003c!-- 不影响原有XML注释 --\u003e\r\n\r\n    // 你也可以加入逻辑删除表达式\r\n    @{this.tryLogicallyDelete.useAndQuery}\r\n    \r\n    // 或者使用乐观锁表达式\r\n    @{this.tryOptimisticLock.useAndQuery}\r\n\u003c/select\u003e\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持各种主键生成策略\r\n\r\n目前插件主要支持以下四种主键生成策略，使用 `@Id` 标识主键，然后使用 `@GeneratedKey` 对主键生成策略进行配置。\r\n\r\n```java\r\n// 省略各种注解配置\r\npublic class YouBean {\r\n    \r\n    @Id\r\n    // 1、使用JDBC的自增主键获取方式\r\n    @GeneratedKey( useGeneratedKeys = true )\r\n    \r\n    // 2、直接生成主键值，插件提供两种默认主键值生成器（SnowFlakeId/UUID）\r\n    // @GeneratedKey( valueProvider = SnowFlakeIdValueProvider.class )\r\n    // @GeneratedKey( valueProvider = UUIDValuePrivoder.class )\r\n    \r\n    // 3、对于不支持JDBC获取自增主键值的数据库来说，可以像下面这样使用：\r\n    // 具体参照com.viiyue.plugins.mybatis.enums.AutoIncrement里面的枚举值，\r\n    // 里面预置了部分获取自增主键的SQL，可以直接写枚举名字，没有的话也可以自己写SQL脚本。\r\n    // @GeneratedKey( statement = \"MYSQL\" ) // MYSQL是枚举名，通过枚举找到对应SQL脚本\r\n    // @GeneratedKey( statement = \"SELECT T_USER.YYYY()\" ) // 直接写SQL脚本\r\n    \r\n    // 4、自定义自增主键SQL提供者\r\n    // 如果枚举里面没有你需要的，可以通过statementProvider来提供你自己的SQL主键查询\r\n    // @GeneratedKey( statementProvider = OracleAutoIncrementStatementProvider.class )\r\n    private Long id;\r\n    \r\n}\r\n\r\n// 自定义自增主键SQL脚本\r\npublic class OracleAutoIncrementStatementProvider implements AutoIncrementStatementProvider {\r\n     @Override\r\n     public String getAutoIncrementSqlStatement( GeneratedKeyInfo info ) {\r\n         return \"SELECT \" + info.getTableName() + \".NEXTVAL FROM DUAL\";\r\n     }\r\n}\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持多主键场景\r\n\r\n\u003e Bean的定义\r\n\r\n可以对多个主键字段进行 `@Id` 标注，没有特殊指明的话，默认会使用对象中第一个标注的主键，否则将会使用 `@Id(primary=true)` 的那一个主键。\r\n\r\n```java\r\n// 省略各种注解配置\r\npublic class YouBean {\r\n\r\n    @Id\r\n    private Long id;\r\n\r\n    @Id(primary = true)\r\n    private Long id2;\r\n    \r\n}\r\n```\r\n\r\n\u003e 使用上的区别\r\n\r\n```java\r\nmapper.selectByPrimaryKey(PK); // 使用默认主键\r\nmapper.selectByPrimaryKeyIndex(Index, PK); // 使用指定下标的主键，多主键顺序由实体Bean决定\r\nmapper.selectByPrimaryKeyGroup(Pk...); // 使用默认主键\r\nmapper.selectByPrimaryKeyGroupIndex(Index, PK...); // 使用指定下标的主键，多主键顺序由实体Bean决定\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 更方便快捷的条件查询\r\n\r\n```java\r\nExample example = null;\r\n\r\n// query\r\n// 方法后面可以直接跟各种Where条件\r\nexample = Example.query(User.class).equal(\"id\", 1L).lt(\"age\", 60).xxx(...);\r\n\r\n// select\r\n// 该方法可以对列进行操作，条件筛选的话使用when()来桥接\r\nexample = Example.select(User.class).includes( \"id\", \"loginName\", \"password\" );\r\nexample.when().equal(\"id\", 1L).lt(\"age\", 60).xxx(...);\r\n\r\n// update\r\n// 使用set/values可以对单个字段进行设值，不支持乐观锁\r\nexample = Example.update(User.class).set(xx, yy, zz).values(XX, YY, ZZ);\r\nexample.when().equal(\"id\", 1L).lt(\"age\", 60).xxx(...);\r\n\r\n// update\r\n// 还可以绑定某个实体对象来修改\r\nUser user = null;\r\nExample.update(User.class).bind(user).when().equal(\"id\", 1L).xxx(...);\r\n\r\n// 具体使用\r\nmapper.selectByExample(example);\r\nmapper.updateByExample(example);\r\nmapper.deleteByExample(example);\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持聚合函数统计\r\n\r\n```java\r\nExample example = null;\r\n\r\n// 支持多字段统计，* 仅能在count函数中使用，其他函数使用会出现异常\r\nexample = Example.count(User.class, \"*\", ...); // 统计行数\r\nexample = Example.summation(User.class, \"price\", \"num\", ...); // 求和\r\nexample = Example.maximum(User.class, \"price\", \"num\", ...); // 求最大值\r\nexample = Example.minimum(User.class, \"price\", \"num\", ...); // 求最小值\r\nexample = Example.average(User.class, \"price\", \"num\", ...); // 求平均值\r\n\r\n// 条件筛选\r\nexample.when().equal(\"id\", 1L).lt(\"age\", 60).xxx();\r\n\r\n// 统计单个值，为了兼容不同的数据类型，统一使用BigDecimal接口，大家可自行转换成需要的数据类型\r\n// 这种情况只能统计单列，如果统计多个字段，会出现SQL异常，此时请使用下面这种方式\r\nBigDecimal result = mapper.selectStatisticByAggregateFunction(example);\r\n\r\n// 统计多列，返回的是对应的实体对象，统计的字段值会自动封装到对象同名字段中\r\nList\u003cDTO\u003e results = mapper.selectStatisticListByAggregateFunction(example);\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持数据库乐观锁\r\n\r\n只需要在你的字段上标注 `@Version` 即可，**乐观锁注解只能出现一次**，默认为版本自增实现，数据类型支持 `Short`、`Integer`、`Long`、`Timestamp`，还可以选择雪花版本值，甚至你可以自己实现版本值的获取，实现 `NextVersionProvider` 接口即可。\r\n\r\n```java\r\n// 省略各种注解配置\r\npublic class User {\r\n    @Version\r\n    // 默认：DefaultNextVersionProvider.class\r\n    // @Version(nextVersion = SnowFlakeIdNextVersionProvider.class)\r\n    private Long version;\r\n}\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持各种逻辑删除\r\n\r\n逻辑删除需要配合 `@LogicallyDelete` 注解一起使用，如无任何注解配置，方法执行将会抛出异常，**只可配置一次**。\r\n\r\n```java\r\n// 逻辑删除所有\r\nmapper.logicallyDeleteAll();\r\n\r\n// 根据特定条件逻辑删除部分\r\nmapper.logicallyDelete(Object);\r\n\r\n// 通过主键逻辑删除指定数据\r\nmapper.logicallyDeleteByPrimaryKey(PK);\r\n\r\n// 通过主键数组逻辑删除特定数据\r\nmapper.logicallyDeleteByPrimaryKeyGroup(Pk...);\r\n\r\n// 多主键情况下，通过主键下标和主键值逻辑删除特定数据\r\nmapper.logicallyDeleteByPrimaryKeyIndex(Integer, Pk);\r\n\r\n// 多主键情况下，通过主键下标和主键数组逻辑删除特定数据\r\nmapper.logicallyDeleteByPrimaryKeyIndexGroup(Index, Pk...);\r\n\r\n// 通过自定义条件筛选逻辑删除特定数据\r\nmapper.logicallyDeleteByExample(example);\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持逻辑删除数据的恢复\r\n\r\n数据恢复也需要配合 `@LogicallyDelete` 注解一起使用，如无任何注解配置，方法执行将会抛出异常。\r\n\r\n```java\r\n// 查询所有被逻辑删除过的数据\r\nmapper.selectAllDeleted();\r\n\r\n// 根据特定条件还原指定数据\r\nmapper.restore(Object);\r\n\r\n// 还原所有被逻辑删除过的数据\r\nmapper.restoreAllDeleted();\r\n\r\n// 通过主键还原指定Id的数据\r\nmapper.restoreByPrimaryKey(Pk);\r\n\r\n// 通过主键数组批量还原数据\r\nmapper.restoreByPrimaryKeyGroup(PK...);\r\n\r\n// 多主键的情况，通过指定主键下标和主键值还原特定数据\r\nmapper.restoreByPrimaryKeyIndex(Integer, Pk);\r\n\r\n// 多主键的情况，通过指定主键下标和主键数组还原特定数据\r\nmapper.restoreByPrimaryKeyIndexGroup(Index, Pk...);\r\n\r\n// 通过自定义条件筛选还原特定数据\r\nmapper.restoreByExample(example);\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持查询自定义返回Bean类型\r\n\r\nMapper接口提供三个泛型参数，依次为\u003c数据库实体类型，返回数据类型，主键类型\u003e。对于返回数据类型你可以任意定义，但是 **ResultMap** 结果映射只会生成和 **数据库实体** 同名的匹配字段，其他不匹配的字段值将一直为  `null`。\r\n\r\n```java\r\npublic class YourMapper extends Mapper\u003cUser, UserDTO, Long\u003e {\r\n    // 那么你的返回数据类型就是：UserDTO\r\n}\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 支持零MapperXML配置文件\r\n\r\n因为插件通过Mybatis的注解 `@SelectProvider`、`@UpdateProvider`、`@InsertProvider`、`@DeleteProvider` 来提供基础 `SqlSource` ，所以即使你没有配置任何XML也是可以正常工作的。\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n\r\n## 扩展插件Api\r\n\r\nMybatis提供的注解SQL功能本身就是一种扩展机制，所以扩展就很好理解了，你可以写自己的@xxxProvider，也可以在插件的基础上实现 `DynamicProvider` 进而扩展插件的Api，这样的话你就可以在通用的Mapper上调用你自己的Api了。\r\n\r\n\u003e 接口定义，需要继承Marker\r\n\r\n```java\r\npublic interface Mapper\u003cDO, DTO, PK extends Serializable\u003e extends Marker\u003cDO, DTO, PK\u003e {\r\n    @SelectProvider( type = YourProvider.class, method = DynamicProvider.dynamicSQL )\r\n    List\u003cDTO\u003e selectCustomApi( @Param(\"param1\") String param1, @Param(\"param2\") String param2 );\r\n}\r\n```\r\n\r\n\u003e 具体实现，需要继承DynamicProvider\r\n\r\n```java\r\npublic final class YourProvider extends DynamicProvider {\r\n    public String selectCustomApi( MappedStatement ms ) {\r\n        return \"[select] @{this.columns} [from] @{this.table} [where] @{this.column.name} = #{param1} [and] @{this.column.xxx} = #{param2}\";\r\n    }\r\n}\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 提供各种场景的日志打印\r\n\r\n\u003e 编译日志，需要开启 enableCompilationLog 配置\r\n\r\n```\r\n... --------------------------------------------------------------------------------\r\n... ----- Target: YourMapper( BaseSelectProvider )\r\n... -- Namespace: xxx.xxx.xxx.YourMapper.selectAll\r\n... Template SQL: [select] @{this.columns} [from] @{this.table} @{this.tryLogicallyDelete.useWhereQuery} @{this.defaultOrderBy}\r\n... Compiled SQL: SELECT `id`, `name`, `version` FROM `t_user` WHERE deleted = 'N' ORDER BY `id` DESC\r\n... ------- Time: 1ms\r\n... --------------------------------------------------------------------------------\r\n```\r\n\r\n\u003e 实时动态日志，需要开启 enableRuntimeLog 配置\r\n\r\n```\r\n... --------------------------------------------------------------------------------\r\n... ==\u003e Compile runtime SQL ...\r\n... --------------------------------------------------------------------------------\r\n... ==\u003e - Template: SELECT `id`, `name`, `version` FROM `t_user` %{this.where($).tryLogicallyDeleteQuery} ORDER BY `id` DESC\r\n... ==\u003e - Compiled: SELECT `id`, `name`, `version` FROM `t_user` WHERE deleted = 'N' AND `name` = #{name} ORDER BY `id` DESC\r\n... ==\u003e Parameters: xxx.xxx.xxx.User@145eaa29\r\n... \u003c== ----- Time: 7ms\r\n... --------------------------------------------------------------------------------\r\n... ==\u003e  Preparing: SELECT `id`, `name`, `version` FROM `t_user` WHERE delete = 'N' AND `name` = ? ORDER BY `id` DESC \r\n... ==\u003e Parameters: xxx(String)\r\n... \u003c==      Total: 3\r\n... --------------------------------------------------------------------------------\r\n```\r\n\r\n[回到顶部](#功能列表)\r\n\r\n\r\n\r\n## 关于作者\r\n\r\n- 邮箱：tangxbai@hotmail.com\r\n- 掘金： https://juejin.im/user/5da5621ce51d4524f007f35f\r\n- 简书： https://www.jianshu.com/u/e62f4302c51f\r\n- Issuse：https://github.com/tangxbai/mybatis-mapper/issues\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangxbai%2Fmybatis-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftangxbai%2Fmybatis-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangxbai%2Fmybatis-mapper/lists"}