TK mapper与 PageHelper

TK mapper(通用Mapper)和MP mapepr(MyBatis-Plus)是mybatis两大插件,功能相同,都提供了常规的增删改查操作,增强mybatis的功能,篇幅有限,文章仅说下两者的区别!

PageHelper是一个分页插件

目录

TK mapper

1.Spring Boot 集成

2.Example 用法

3.Mapper接口

4.Mybatis Geneator 概述

5.TK mapper专用代码生成器

TK与mybatis-plus的区别

PageHelper

 


TK mapper

官方wiki:

https://gitee.com/free/Mapper/wikis/Home

JavaDoc

https://apidoc.gitee.com/free/Mapper/

demo(不看官网系列)

码云:https://gitee.com/liuyandeng/tkmapper-generator

GitHub:https://github.com/877507054/tkmapper-generator

 

项目升级

只需要升级版本号,例如通用 Mapper:



  tk.mybatis

  mapper

  版本号

MyBatis 通用 Mapper4(tk mapepr4)更新日志(了解)

此次更新最大的变化是项目结构调整了,将原来的 mapper 拆分成了 core, base, extra, generator, spring 五个子模块,将独立的 mapper-weekend 和 spring-boot-starter 项目添加到 mapper 中作为两个子项目,拆分后的整个项目如下:

all - 为了方便开发人员使用,屏蔽模块细节,提供的整合,下面两个子模块是具体实现,具体包含了 core, base, extra, generator, spring, weekend 六个项目。

dependencies - 以依赖方式整合,包含 tk.mybatis:mapper 的完整功能。

mapper - 通过 maven-shade-plugin 打包整合,和原来的 tk.mybatis:mapper 完全一样,并且 Maven 坐标就是 tk.mybatis:mapper。

base - 所有 Mapper 等接口的实现,独立出来后方便整体替换这部分实现。

core - 通用 Mapper 的核心,依赖 core 可以实现自己的通用方法,base 就是以此为依赖的一种实现。

extra - base 方法扩展,提供有局限性的通用接口。

generator - 代码生成器,包含了通用 Mapper 代码生成器和一个通用的全功能代码生成器插件。

spring - 通用 Mapper 和 Spring 集成需要的关键类,重写了 MyBatis 几个实现类。

spring-boot-starter - 通用 Mapper 和 Spring Boot 集成。

weekend - 基于 Java8 方法引用的 Example 替代对象 Weekend,可以避免字符串形式的字段名。

 

1.Spring Boot 集成

Spring Boot 在微服务领域中已经成为主流。

Mapper 如何同 Spring Boot 进行集成?

基本上分为两大类。

  • 基于 starter 的自动配置
  • 基于 @MapperScan 注解的手工配置

mapper-spring-boot-starter

在 starter 的逻辑中,如果你没有使用 @MapperScan 注解,你就需要在你的接口上增加 @Mapper 注解,否则 MyBatis 无法判断扫描哪些接口。

这里的第一种用法没有用 @MapperScan 注解,所以你需要在所有接口上增加 @Mapper 注解。

以后会考虑增加其他方式。

你只需要添加通用 Mapper 提供的 starter 就完成了最基本的集成,依赖如下:



  tk.mybatis

  mapper-spring-boot-starter

  版本号


最新版本号如上所示,你也可以从下面地址查看:点击

注意:引入该 starter 时,和 MyBatis 官方的 starter 没有冲突,但是官方的自动配置不会生效!

如果你需要对通用 Mapper 进行配置,你可以在 Spring Boot 的配置文件中配置 mapper. 前缀的配置。

例如在 yml 格式中配置:

 

mapper:

  mappers:

    - tk.mybatis.mapper.common.Mapper

    - tk.mybatis.mapper.common.Mapper2

  notEmpty: true

 

在 properties 配置中:

mapper.mappers=tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.common.Mapper2

mapper.notEmpty=true

mappers

在 4.0 以前这是一个非常重要的参数,当时只有通过 mappers 配置过的接口才能真正调用,由于很多人不注意看文档,通用 Mapper 90% 的问题都出在这个参数上。

4.0 之后,增加了一个 @RegisterMapper 注解,通用 Mapper 中提供的所有接口都有这个注解,有了该注解后,通用 Mapper 会自动解析所有的接口,如果父接口(递归向上找到的最顶层)存在标记该注解的接口,就会自动注册上。因此 4.0 后使用通用 Mapper 提供的方法时,不需要在配置这个参数。

当你自己扩展通用接口时,建议加上该注解,否则就要配置 mappers 参数。

notEmpty

insertSelective 和 updateByPrimaryKeySelective 中,是否判断字符串类型 !=''。

配置方式:

notEmpty=true

更多配置:点击

 

@MapperScan 注解配置

你可以给带有 @Configuration 的类配置该注解,或者直接配置到 Spring Boot 的启动类上,如下:

@tk.mybatis.spring.annotation.MapperScan(basePackages = "扫描包")
@SpringBootApplication
public class SampleMapperApplication implements CommandLineRunner {

 

 

2.Example 用法

条件构造器

1.通用 Example

TK mapper与 PageHelper_第1张图片

 

查询

示例:

Example example = new Example(Country.class);
example.setForUpdate(true);
example.createCriteria().andGreaterThan("id", 100).andLessThan("id",151);
example.or().andLessThan("id", 41);
List countries = mapper.selectByExample(example);

日志:

DEBUG [main] - ==>  Preparing: 
SELECT id,countryname,countrycode FROM country WHERE ( id > ? and id < ? ) or ( id < ? ) ORDER BY id desc FOR UPDATE 
DEBUG [main] - ==> Parameters: 100(Integer), 151(Integer), 41(Integer)
DEBUG [main] - <==      Total: 90

动态 SQL

示例:

Example example = new Example(Country.class);
Example.Criteria criteria = example.createCriteria();
if(query.getCountryname() != null){
    criteria.andLike("countryname", query.getCountryname() + "%");
}
if(query.getId() != null){
    criteria.andGreaterThan("id", query.getId());
}
List countries = mapper.selectByExample(example);

日志:

DEBUG [main] - ==>  Preparing: 
SELECT id,countryname,countrycode FROM country WHERE ( countryname like ? ) ORDER BY id desc 
DEBUG [main] - ==> Parameters: China%(String)
DEBUG [main] - <==      Total: 1

排序

示例:

Example example = new Example(Country.class);
example.orderBy("id").desc().orderBy("countryname").orderBy("countrycode").asc();
List countries = mapper.selectByExample(example);

日志:

DEBUG [main] - ==>  Preparing: 
SELECT id,countryname,countrycode FROM country order by id DESC,countryname,countrycode ASC 
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 183

去重

示例:

Example example = new Example();
//设置 distinct
example.setDistinct(true);
example.createCriteria().andCountrynameLike("A%");
example.or().andIdGreaterThan(100);
List countries = mapper.selectByExample(example);

日志:

DEBUG [main] - ==>  Preparing: 
SELECT distinct id,countryname,countrycode FROM country WHERE ( countryname like ? ) or ( Id > ? ) ORDER BY id desc 
DEBUG [main] - ==> Parameters: A%(String), 100(Integer)
DEBUG [main] - <==      Total: 95

设置查询列

示例:

Example example = new Example(Country.class);
example.selectProperties("id", "countryname");
List countries = mapper.selectByExample(example);

日志:

DEBUG [main] - ==>  Preparing: 
SELECT id , countryname FROM country ORDER BY id desc 
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 183

除了这里提到的方法外,还有很多其他的方法,可以查看 Example 源码进行了解。

2.Example.builder 方式

示例:

Example example = Example.builder(Country.class)
        .select("countryname")
        .where(Sqls.custom().andGreaterThan("id", 100))
        .orderByAsc("countrycode")
        .forUpdate()
        .build();
List countries = mapper.selectByExample(example);

日志:

DEBUG [main] - ==>  Preparing: 
SELECT countryname FROM country WHERE ( id > ? ) order by countrycode Asc FOR UPDATE 
DEBUG [main] - ==> Parameters: 100(Integer)
DEBUG [main] - <==      Total: 83

3.Weekend

使用 以上中的 Example 时,需要自己输入属性名,例如 "countryname",假设输入错误,或者数据库有变化,这里很可能就会出错,因此基于 Java 8 的方法引用是一种更安全的用法,如果你使用 Java 8,你可以试试 Weekend。

 

示例:

List selectByWeekendSql = mapper.selectByExample(
        new Example.Builder(Country.class)
                .where(WeekendSqls.custom().andLike(Country::getCountryname, "%a%")
                        .andGreaterThan(Country::getCountrycode, "123"))
                .build());

日志:

DEBUG [main] - ==>  Preparing: 
SELECT id,countryname,countrycode FROM country WHERE ( countryname like ? and countrycode > ? ) 
DEBUG [main] - ==> Parameters: %a%(String), 123(String)
DEBUG [main] - <==      Total: 151

在代码中的 Country::getCountryname 就是方法引用,通过该方法可以自动转换对应的列名。

3.Mapper接口

public interface BaseMapper extends Mapper, MySqlMapper {}

这个方法提供了基本的增删改查

TK mapper与 PageHelper_第2张图片

 

4.Mybatis Geneator 概述

在MBG中,最主要也最重要的就是XML配置文件.

配置文件头


根节点

子元素

 (0个或1个)
 (0个或多个)
 (1个或多个)

这个元素用来指定外部的属性元素,不是必须的元素。元素用于指定一个需要在配置中解析使用的外部属性文件

案例

 

最常见的用法是通过这个属性指定驱动的路径

 

在MBG的配置中,至少需要有一个元素。

元素用于指定生成一组对象的环境。例如指定要连接的数据库,要生成对象的类型和要处理的数据库中的表。

属性

id:

必须,用来唯一确定一个元素

可选属性

defaultModelType:

定义了MBG如何生成**实体类**

这个属性有以下可选值:

conditional:*这是默认值*,这个模型和下面的hierarchical类似,除了如果那个单独的类将只包含一个字段,将不会生成一个单独的类。 因此,如果一个表的主键只有一个字段,那么不会为该字段生成单独的实体类,会将该字段合并到基本实体类中。

flat:该模型为每一张表只生成一个实体类。这个实体类包含表中的所有字段。**这种模型最简单,推荐使用。**

hierarchical:如果表有主键,那么该模型会产生一个单独的主键实体类,如果表还有BLOB字段, 则会为表生成一个包含所有BLOB字段的单独的实体类,然后为所有其他的字段生成一个单独的实体类。 MBG会在所有生成的实体类之间维护一个继承关系。

targetRuntime:

此属性用于指定生成的代码的运行时环境。MyBatis3:*是默认值*,一般情况下使用默认值即可

introspectedColumnImpl:

该参数可以指定扩展org.mybatis.generator.api.IntrospectedColumn该类的实现类。

子元素

这些子元素(有严格的配置顺序)包括:

  •  (0个或多个)
  •  (0个或多个)
  •  (0个或1个)
  •  (1个)
  •  (0个或1个)
  •  (1个)
  •  (0个或1个)
  •  (0个或1个)
  •  (1个或多个)

     

    下面一一讲解:

     

    支持的属性:

    • autoDelimitKeywords
    • beginningDelimiter
    • endingDelimiter
    • javaFileEncoding
    • javaFormatter
    • xmlFormatter

    由于这些属性比较重要,这里一一讲解。

    autoDelimitKeywords:

    当表名或者字段名为SQL关键字的时候,可以设置该属性为true,MBG会自动给表名或字段名添加**分隔符**。

    beginningDelimiter和endingDelimiter属性。

    由于beginningDelimiter和endingDelimiter的默认值为双引号("),在Mysql中不能这么写,所以还要将这两个默认值改为**反单引号(`)**,配置如下:

    
    
      

    javaFileEncoding:

    设置要使用的Java文件的编码,默认使用当前平台的编码,只有当生产的编码需要特殊指定时才需要使用,一般用不到。

    javaFormatter和xmlFormatter属性

    如果你想使用模板来定制生成的java文件和xml文件的样式,你可以通过指定这两个属性的值来实现

     

     

    元素用来定义一个插件。插件用于扩展或修改通过MyBatis Generator (MBG)代码生成器生成的代码。

     

     

    用于指定数据库连接信息,该元素必选,并且只能有一个。

     

     

    这个元素的配置用来指定JDBC类型和Java类型如何转换。

     

    生成的代码中可以包含**注释信息**,生成表或字段的备注信息。

     

     

    
    
    
    注:项目路径为个人测试地址

     

     

     

    
    
    


     

     

    
    
    
    

    该元素用来配置要通过内省的表。只有配置的才会生成实体类和其他文件。

    <table tableName="test">table>

    必选属性

    该元素有一个必选属性:

    tableName:指定要生成的表名,可以使用SQL通配符匹配多个表。

    可选属性

    该元素包含多个可选属性:

    schema:数据库的schema,可以使用SQL通配符匹配。如果设置了该值,生成SQL的表名会变成如schema.tableName的形式。

    catalog:数据库的catalog,如果设置了该值,生成SQL的表名会变成如catalog.tableName的形式。

    alias:如果指定,这个值会用在生成的select查询SQL的表的别名和列名上。 列名会被别名为 alias_actualColumnName(别名_实际列名) 这种模式。

    domainObjectName:生成对象的基本名称。如果没有指定,MBG会自动根据表名来生成名称。

    enableXXX:XXX代表多种SQL方法,该属性用来指定是否生成对应的XXX语句。

    selectByPrimaryKeyQueryId:DBA跟踪工具会用到,具体请看详细文档。

    selectByExampleQueryId:DBA跟踪工具会用到,具体请看详细文档。

    modelType:和的defaultModelType含义一样,这里可以针对表进行配置,这里的配置会覆盖的defaultModelType配置。

    escapeWildcards:这个属性表示当查询列,是否对schema和表名中的SQL通配符 ('_' and '%') 进行转义。 对于某些驱动当schema或表名中包含SQL通配符时(例如,一个表名是MY_TABLE,有一些驱动需要将下划线进行转义)是必须的。默认值是false。

    delimitIdentifiers:是否给标识符增加**分隔符**。默认false。当catalog,schema或tableName中包含空白时,默认为true。

    delimitAllColumns:是否对所有列添加**分隔符**。默认false。

    子元素

    该元素包含多个可用的子元素,可选属性为:

    constructorBased:和中的属性含义一样。

    ignoreQualifiersAtRuntime:生成的SQL中的表名将不会包含schema和catalog前缀。

    immutable:和中的属性含义一样。

    modelOnly:此属性用于配置是否为表只生成实体类。如果设置为true就不会有Mapper接口。如果配置了,并且modelOnly为true,那么XML映射文件中只有实体对象的映射元素()。如果为true还会覆盖属性中的enableXXX方法,将不会生成任何CRUD方法。

    rootClass:和中的属性含义一样。

    rootInterface:和中的属性含义一样。

    runtimeCatalog:运行时的catalog,当生成表和运行环境的表的catalog不一样的时候可以使用该属性进行配置。

    runtimeSchema:运行时的schema,当生成表和运行环境的表的schema不一样的时候可以使用该属性进行配置。

    runtimeTableName:运行时的tableName,当生成表和运行环境的表的tableName不一样的时候可以使用该属性进行配置。

    selectAllOrderByClause:该属性值会追加到selectAll方法后的SQL中,会直接跟order by拼接后添加到SQL末尾。

    useActualColumnNames:如果设置为true,那么MBG会使用从数据库元数据获取的列名作为生成的实体对象的属性。 如果为false(默认值),MGB将会尝试将返回的名称转换为驼峰形式。 在这两种情况下,可以通过 元素显示指定,在这种情况下将会忽略这个(useActualColumnNames)属性。

    useColumnIndexes:如果是true,MBG生成resultMaps的时候会使用列的索引,而不是结果中列名的顺序。

    useCompoundPropertyNames:如果是true,那么MBG生成属性名的时候会将列名和列备注接起来. 这对于那些通过第四代语言自动生成列(例如:FLD22237),但是备注包含有用信息(例如:"customer id")的数据库来说很有用. 在这种情况下,MBG会生成属性名FLD2237_CustomerId。

    其它子元素

    除了子元素外,

    还包含以下子元素:

    •  (0个或1个)
    •  (0个或1个)
    •  (0个或多个)
    •  (0个或多个)

    下面对这4个元素进行详细讲解。

     

    1.  元素

     

    这个元素最多可以配置一个。

    这个元素用来指定自动生成主键的属性(identity字段或者sequences序列)。如果指定这个元素,MBG在生成insert的SQL映射文件中插入一个元素。 这个元素**非常重要**,这个元素包含下面两个必选属性:

    ·column:生成列的列名。

    ·sqlStatement:将返回新值的 SQL 语句。如果这是一个identity列,您可以使用其中一个预定义的的特殊值。预定义值如下:

    • Cloudscape
    • DB2
    • DB2_MF
    • Derby
    • HSQLDB
    • Informix
    • MySql
    • SqlServer
    • SYBASE
    • JDBC:这会配置MBG使用MyBatis3支持的JDBC标准的生成key来生成代码。 这 是一个独立于数据库获取标识列中的值的方法。 重要: 只有当目标运行为MyBatis3时 才会产生正确的代码。 如果与iBATIS2一起使用目标运行时会产生运行时错误的代码。

    这个元素还包含两个可选属性:

    ·identity:当设置为true时,该列会被标记为identity列, 并且元素会被插入在insert后面。 当设置为false时,会插入到insert之前(通常是序列)。**重要**: 即使您type属性指定为post,您仍然需要为identity列将该参数设置为true。 这将标志MBG从插入列表中删除该列。默认值是false。

     

    ·type:type=post and identity=true的时候生成的中的order=AFTER,当type=pre的时候,identity只能为false,生成的中的order=BEFORE。可以这么理解,自动增长的列只有插入到数据库后才能得到ID,所以是AFTER,使用序列时,只有先获取序列之后,才能插入数据库,所以是BEFORE。

    配置示例一:

       

     

    对应的生成的结果:

    
       
          SELECT LAST_INSERT_ID()
       
       insert into `user login info` (Id, username, logindate, loginip)
       values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{logindate,jdbcType=TIMESTAMP}, #{loginip,jdbcType=VARCHAR})
    

    配置示例二:

    
    
       
    

     


    对应的生成结果:

     

    
    
       
          select SEQ_ID.nextval from dual
       
       insert into `user login info` (Id, username, logindate, loginip)
       values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{logindate,jdbcType=TIMESTAMP},#{loginip,jdbcType=VARCHAR})
    

    2.  元素

     

    该元素最多可以配置一个,使用该元素可以在生成列之前,对列进行重命名。这对那些存在同一前缀的字段想在生成属性名时去除前缀的表非常有用。 例如假设一个表包含以下的列:

    • CUST_BUSINESS_NAME
    • CUST_STREET_ADDRESS
    • CUST_CITY
    • CUST_STATE

    生成的所有属性名中如果都包含CUST的前缀可能会让人不爽。这些前缀可以通过如下方式定义重命名规则:

    注意,在内部,MBG使用java.util.regex.Matcher.replaceAll方法实现这个功能。 请参阅有关该方法的文档和在Java中使用正则表达式的例子。

    匹配一列时,这个元素()会被忽略。优先于重命名的规则。

     

    该元素有一个必选属性:

    searchString:定义将被替换的字符串的正则表达式。

     

    该元素有一个可选属性:

    replaceString:这是一个用来替换搜索字符串列每一个匹配项的字符串。如果没有指定,就会使用空字符串。

    关于

    属性useActualColumnNames对此的影响可以查看完整文档。

     

    3.  元素

    该元素可选,可以配置多个。

    该元素从将某些属性默认计算的值更改为指定的值。

     

    该元素有一个必选属性:

    column:要重写的列名。

     

    该元素有多个可选属性:

    ·property:要使用的Java属性的名称。如果没有指定,MBG会根据列名生成。 例如,如果一个表的一列名为STRT_DTE,MBG会根据

    的useActualColumnNames属性生成STRT_DTE或strtDte。

     

    ·javaType:该列属性值为完全限定的Java类型。如果需要,这可以覆盖由JavaTypeResolver计算出的类型。 对某些数据库来说,这是必要的用来处理**“奇怪的”**数据库类型(例如MySql的unsigned bigint类型需要映射为java.lang.Object)。

     

    ·jdbcType:该列的JDBC类型(INTEGER, DECIMAL, NUMERIC, VARCHAR等等)。 如果需要,这可以覆盖由JavaTypeResolver计算出的类型。 对某些数据库来说,这是必要的用来处理怪异的JDBC驱动 (例如DB2的LONGVARCHAR类型需要为iBATIS 映射为VARCHAR)。

     

    ·typeHandler:用户定义的需要用来处理这列的类型处理器。它必须是一个继承iBATIS的·TypeHandler类或TypeHandlerCallback接口(该接口很容易继承)的全限定的类名。如果没有指定或者是空白,iBATIS会用默认的类型处理器来处理类型。**重要**:MBG不会校验这个类型处理器是否存在或者可用。 MGB只是简单的将这个值插入到生成的SQL映射的配置文件中。

     

    ·delimitedColumnName:指定是否应在生成的SQL的列名称上增加**分隔符**。 如果列的名称中包含空格,MGB会自动添加**分隔符**, 所以这个重写只有当列名需要强制为一个合适的名字或者列名是数据库中的保留字时是必要的。

    配置示例:

       

     


    4.  元素

     

    该元素可选,可以配置多个。

    该元素可以用来屏蔽不需要生成的列。

     

    该元素有一个必选属性:

    column:要忽略的列名。

     

    该元素还有一个可选属性:

    delimitedColumnName:匹配列名的时候是否区分大小写。如果为true则区分。默认值为false,不区分大小写。

     

     

     

    5.TK mapper专用代码生成器

    使用Java编码方式运行MBG

    加入依赖

    
    
    
        tk.mybatis
        mapper
        4.0.0
    

    通用 Mapper 专用代码生成器生成的 Model 会在原有基础上增加 @Table,@Id,@Column 等注解,方便自动会数据库字段进行映射。

    Java代码很容易:

    Java代码

    package com.jbdp.generator;
    import org.mybatis.generator.api.MyBatisGenerator;
    import org.mybatis.generator.config.Configuration;
    import org.mybatis.generator.config.xml.ConfigurationParser;
    import org.mybatis.generator.internal.DefaultShellCallback;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Generator {
       public static void main(String[] args) throws Exception {
          // TODO Auto-generated method stub
          List warnings = new ArrayList();
            boolean overwrite = true;
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config =  
    
    cp.parseConfiguration(getResourceAsStream("generator/generatorConfig.xml"));
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            myBatisGenerator.generate(null);
            for (String warning : warnings) {
                System.out.println(warning);
            }
       }
    }

    这段代码容易,最主要的一个内容是"generatorConfig.xml",我们应该如何配置该类,下面是一个generatorConfig.xml的例子.

     

    Xml配置

    generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">


    <generatorConfiguration>
        <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
            <property name="javaFileEncoding" value="UTF-8"/>
            <property name="useMapperCommentGenerator" value="false"/>

            <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
                <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
                <property name="caseSensitive" value="true"/>
                <property name="forceAnnotation" value="true"/>
                <property name="beginningDelimiter" value="`"/>
                <property name="endingDelimiter" value="`"/>
            plugin>

            <jdbcConnection driverClass="org.hsqldb.jdbcDriver"
                            connectionURL="jdbc:hsqldb:mem:generator"
                            userId="sa"
                            password="">
            jdbcConnection>

            
            <javaModelGenerator targetPackage="test.model"
                                targetProject="generator/src/test/java"/>

            <table tableName="user_info">
                <generatedKey column="id" sqlStatement="JDBC"/>
            table>


            <table tableName="country">
                <generatedKey column="id" sqlStatement="JDBC"/>
            table>


        context>

    generatorConfiguration>

     

    MapperPlugin配置

    和一般的配置相比,这里只是多了一个插件的配置:

    <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
        <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
        <property name="caseSensitive" value="true"/>
        <property name="forceAnnotation" value="true"/>
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

    plugin>

     

    这里最关键的参数就是 mappers,配置后生成的 Mapper 接口都会自动继承上改接口,如果你定义了一个自己的基础接口,例如:

    package xxx.base;
    import tk.mybatis.mapper.common.Mapper;
    
    import tk.mybatis.mapper.common.MySqlMapper;
    /**
     * 继承自己的MyMapper
     */
    
    public interface MyMapper extends Mapper, MySqlMapper {
        //TODO
        //FIXME 特别注意,该接口不能被扫描到,否则会出错
    }

    在配置插件时,可以配置为:

     

    其他参数的含义:

    ·caseSensitive 是否区分大小写,默认值 false。如果数据库区分大小写,这里就需要配置为 true,这样当表名为 USER 时,会生成 @Table(name = "USER") 注解,否则使用小写 user 时会找不到表。

    ·forceAnnotation 是否强制生成注解,默认 false,如果设置为 true,不管数据库名和字段名是否一致,都会生成注解(包含 @Table 和 @Column)。

    ·beginningDelimiter endingDelimiter 开始和结束分隔符,对于有关键字的情况下适用。

    ·useMapperCommentGenerator 是否使用通用 Mapper 提供的注释工具,默认 true 使用,这样在生成代码时会包含字段的注释(目前只有 mysql 和 oracle 支持),设置 false后会用默认的,或者你可以配置自己的注释插件。

    ·generateColumnConsts 在生成的 model中,增加字段名的常量,便于使用 Example 拼接查询条件的时候使用。

    ·lombok 增加 model 代码生成时,可以直接生成 lombok 的 @Getter@Setter@ToString@Accessors(chain = true) 四类注解, 使用者在插件配置项中增加  即可生成对应包含注解的 model 类。

     

     

    在上面

    
       
    

    SQL 中的 {1} 代表的是对应表的大写形式,{0} 是小写形式,这个配置生成的代码会像下面这样:

    public class Country {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY,
                generator = "select SEQ_COUNTRY.nextval from dual")
        private Integer id;
        // 省略其他
    }

    这段配置介绍完了,之后运行前面的JAVA方法,就会生成对应的文件。该文件的样式在最后贴个例子。

    使用 Maven 执行MBG

    这是一个例子

    Maven 中的插件配置如下:

    
        
            maven-compiler-plugin
            
                ${jdk.version}
                ${jdk.version}
            
        
        
            org.mybatis.generator
            mybatis-generator-maven-plugin
            1.3.6
            
                
                    ${basedir}/src/main/resources/generator/generatorConfig.xml
                
                true
                true
            
            
                
                    mysql
                    mysql-connector-java
                    5.1.29
                
    
                
                    tk.mybatis
                    mapper
                    4.0.0
                
            
        
    

    在插件中配置了配置文件的路径,覆盖和输出详细日志三个参数。

    除此之外需要特别注意的是 ,MBG 配置中用到的所有外部代码都必须通过依赖方式配置在这里,否则运行时会提示找不到对应的类而报错。这里有两个必须的依赖,一个是 JDBC 驱动,另一个是 Mapper 的插件。

    下面看配置文件generatorConfig.xml

    generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    <generatorConfiguration>
        <properties resource="config.properties"/>

        <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
            <property name="beginningDelimiter" value="`"/>
            <property name="endingDelimiter" value="`"/>

            <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
                <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
                <property name="caseSensitive" value="true"/>
            plugin>

            <jdbcConnection driverClass="${jdbc.driverClass}"
                            connectionURL="${jdbc.url}"
                            userId="${jdbc.user}"
                            password="${jdbc.password}">
            jdbcConnection>

            <javaModelGenerator targetPackage="com.isea533.mybatis.model"
                                targetProject="src/main/java"/>

            <sqlMapGenerator targetPackage="mapper"
                             targetProject="src/main/resources"/>

            <javaClientGenerator targetPackage="com.isea533.mybatis.mapper"
                                 targetProject="src/main/java"
                                 type="XMLMAPPER"/>

            <table tableName="user_info">
                <generatedKey column="id" sqlStatement="JDBC"/>
            table>


        context>

    generatorConfiguration>

     

    这里和之前相差不多,只是通过  引入了外部属性文件,在  配置时,使用的属性文件中的参数。

    运行

    在 pom.xml 这一级目录的命令行窗口执行 mvn mybatis-generator:generate即可(前提是配置了mvn)。

     

    生成的代码

    下面是自动生成的代码的例子,这些例子可以在Mybatis-Spring这里找到。

    一、实体Country

    package com.isea533.mybatis.model;
    import javax.persistence.*;
    @Table(name = "country")
    
    public class Country {
        /**
         * 主键
         */
        @Id
        @Column(name = "Id")
        @GeneratedValue(generator = "JDBC")
        private Integer id;
    
        /**
         * 名称
         */
        private String countryname;
    
        /**
         * 代码
         */
        private String countrycode;
    
        /**
         * 获取主键
         *
         * @return Id - 主键
         */
        public Integer getId() {
            return id;
        }
    
        /**
         * 设置主键
         *
         * @param id 主键
         */
        public void setId(Integer id) {
            this.id = id;
        }
    
        /**
         * 获取名称
         *
         * @return countryname - 名称
         */
        public String getCountryname() {
            return countryname;
        }
    
        /**
         * 设置名称
         *
         * @param countryname 名称
         */
        public void setCountryname(String countryname) {
            this.countryname = countryname;
        }
    
        /**
         * 获取代码
         *
         * @return countrycode - 代码
         */
        public String getCountrycode() {
            return countrycode;
        }
    
        /**
         * 设置代码
         *
         * @param countrycode 代码
         */
        public void setCountrycode(String countrycode) {
            this.countrycode = countrycode;
        }
    }
    
    

    可以看到这里生成的注释是有意义的内容,注释来源于数据库表字段的注释。

    二、Mapper接口CountryMapper

     

    
    package com.isea533.mybatis.mapper;
    import com.isea533.mybatis.model.Country;
    
    import tk.mybatis.mapper.common.Mapper;
    public interface CountryMapper extends Mapper {
    }
    
    

    接口自动继承配置的通用Mapper接口,自动包含泛型实体。

     

    三、Mapper.xml文件CountryMapper.xml

    
    
    
    
        
            
            
            
            
        

    xml文件只包含了实体的resultMap映射配置

    基于模板的插件TemplateFilePlugin

    代码生成器是基于 MBG 插件的,所以需要配合 MBG 使用。

    xml version="1.0" encoding="UTF-8"?>
    generatorConfiguration
    PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
    "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

    <generatorConfiguration>
       <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
          <property name="javaFileEncoding" value="UTF-8"/>
          
          

          
          <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
             <property name="mappers" value="tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.hsqldb.HsqldbMapper"/>
             <property name="caseSensitive" value="true"/>
             <property name="forceAnnotation" value="true"/>
             <property name="beginningDelimiter" value="`"/>
             <property name="endingDelimiter" value="`"/>
          plugin>

          
          <plugin type="tk.mybatis.mapper.generator.TemplateFilePlugin">
             <property name="targetProject" value="src/test/java"/>
             <property name="targetPackage" value="test.mapper"/>
             <property name="templatePath" value="generator/mapper.ftl"/>
             <property name="mapperSuffix" value="Dao"/>
             <property name="fileName" value="${tableClass.shortClassName}${mapperSuffix}.java"/>
          plugin>

          <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                      connectionURL="jdbc:mysql://localhost:3306/test"
                      userId="root"
                      password="">
          jdbcConnection>

          
          <javaModelGenerator targetPackage="test.model" targetProject="./src/test/java"/>

          <table tableName="user%">
             <generatedKey column="id" sqlStatement="JDBC"/>
          table>
       context>
    generatorConfiguration>

     

    在这个配置中,我们只关注 tk.mybatis.mapper.generator.TemplateFilePlugin

    下面介绍必备的属性。

    1. targetProject

    用于指定目标项目,一般是 src/main/java 或者 src/main/resource 这样的目录。 还可以是 src/test/java 或者 src/test/resource 这样的目录。

    在多模块项目中,还能通过相对路径指定为其他的目录,例如:

     

    这个属性值有一个要求,就是目录必须存在,否则不会生成代码!

    2. targetPackage

    用于指定包的部分,虽然是这个名字,实际上就是路径。

    这个属性指定的路径如果不存在,就会自动创建。

    这个属性的值可以为空。

    例如 mapper/admin 用于生成 mapper/admin/ 目录,或者 tk.mybatis.mapper 生成包(本质上还是目录)。

    这个属性还有一个特殊的地方,它还支持使用模板,就和下面的 fileName 一样,举个简单的使用场景。

    你可能在生成前端代码的时候,希望将表对应的 JSP 生成在自己的一个目录中,此时可以配置为:

    模板中可以用到的属性,这里都能用,其他属性后面会介绍。

    通过这个路径也能看出来,配置一个插件只能根据模板在一个指定位置(targetProject 和 targetPackage 决定的目录)生成一个文件。

    3. templatePath

    指定模板路径,可以是任意能够通过 ClassLoader 能够获取的位置,文件类型没有限制。

    例如示例中的 generator/test-one.ftl。

    这个属性必须指定,否则不会生成代码!

    4. fileName

    这个属性用于指定生成文件的名字,这个值支持使用模板,例如上面的 ${tableClass.shortClassName}Test.txt,具体可用的属性会在后面介绍。

    这个属性必须指定,否则不会生成代码!

     

    5. templateFormatter

    这个属性可选,默认使用基于 FreeMarker 的实现!

    默认情况下,你需要添加下面的依赖:

    
       org.freemarker
       freemarker
       2.3.23
    

     

     

    默认的实现类为:tk.mybatis.mapper.generator.formatter.FreemarkerTemplateFormatter。

    这个类实现了两个接口 TemplateFormatter, ListTemplateFormatter。

    这俩接口分别对应下面 singleMode 参数值的 true 和 false。

    也就是一个表生成一个文件,或者多个表生成一个文件。

    对于一般情况下,都是第一种情况。但是在配置文件中,可能会用到多个表的信息。

    如果你想使用其他模板引擎,可以自己实现上面的接口。

    6. singleMode

    上面已经提过,默认为 true。

    一个表生成一个文件时,可用属性可以参考 generator/test-one.ftl,表的属性在 tableClass中。

    多个表生成一个文件时,可用属性可以参考 generator/test-all.ftl,所有表的属性在 tableClassSet 中,通过遍历可以获取单个的信息。

    7. 其他你需要的属性

    模板中需要的特殊信息都可以通过  方法设置,在模板中直接使用这里定义的属性名来使用,后面例子的中的 mapperSuffix 就是这种属性。

    8.可用属性

    在表和实体上可用的所有属性如下:

    特殊:targetPackage值在 ${package} 中。
    
    
    当前时间:
    <#assign dateTime = .now>
    日期:${dateTime?date}
    时间:${dateTime?time}
    格式化:${dateTime?string["yyyy-MM-dd HH:mm:ss"]}
    
    
    所有配置的属性信息:
    <#list props?keys as key>
        ${key} - ${props[key]}
    
    
    实体和表的信息:
    表名:${tableClass.tableName}
    变量名:${tableClass.variableName}
    小写名:${tableClass.lowerCaseName}
    类名:${tableClass.shortClassName}
    全名:${tableClass.fullClassName}
    包名:${tableClass.packageName}
    
    列的信息:
    =====================================
    <#if tableClass.pkFields??>
        主键:
        <#list tableClass.pkFields as field>
            -------------------------------------
            列名:${field.columnName}
            列类型:${field.jdbcType}
            字段名:${field.fieldName}
            注释:${field.remarks}
            类型包名:${field.typePackage}
            类型短名:${field.shortTypeName}
            类型全名:${field.fullTypeName}
            是否主键:${field.identity?c}
            是否可空:${field.nullable?c}
            是否为BLOB列:${field.blobColumn?c}
            是否为String列:${field.stringColumn?c}
            是否为字符串列:${field.jdbcCharacterColumn?c}
            是否为日期列:${field.jdbcDateColumn?c}
            是否为时间列:${field.jdbcTimeColumn?c}
            是否为序列列:${field.sequenceColumn?c}
            列长度:${field.length?c}
            列精度:${field.scale}
        
    
    
    <#if tableClass.baseFields??>
        基础列:
        <#list tableClass.baseFields as field>
            -------------------------------------
            列名:${field.columnName}
            列类型:${field.jdbcType}
            字段名:${field.fieldName}
            注释:${field.remarks}
            类型包名:${field.typePackage}
            类型短名:${field.shortTypeName}
            类型全名:${field.fullTypeName}
            是否主键:${field.identity?c}
            是否可空:${field.nullable?c}
            是否为BLOB列:${field.blobColumn?c}
            是否为String列:${field.stringColumn?c}
            是否为字符串列:${field.jdbcCharacterColumn?c}
            是否为日期列:${field.jdbcDateColumn?c}
            是否为时间列:${field.jdbcTimeColumn?c}
            是否为序列列:${field.sequenceColumn?c}
            列长度:${field.length?c}
            列精度:${field.scale}
        
    
    
    <#if tableClass.blobFields??>
        Blob列:
        <#list tableClass.blobFields as field>
            -------------------------------------
            列名:${field.columnName}
            列类型:${field.jdbcType}
            字段名:${field.fieldName}
            注释:${field.remarks}
            类型包名:${field.typePackage}
            类型短名:${field.shortTypeName}
            类型全名:${field.fullTypeName}
            是否主键:${field.identity?c}
            是否可空:${field.nullable?c}
            是否为BLOB列:${field.blobColumn?c}
            是否为String列:${field.stringColumn?c}
            是否为字符串列:${field.jdbcCharacterColumn?c}
            是否为日期列:${field.jdbcDateColumn?c}
            是否为时间列:${field.jdbcTimeColumn?c}
            是否为序列列:${field.sequenceColumn?c}
            列长度:${field.length?c}
            列精度:${field.scale}
        
    
    
    =====================================
    全部列(包含了pk,base,blob 字段,可用的属性和上面的一样):
    <#if tableClass.allFields??>
        列名 - 字段名
        <#list tableClass.allFields as field>
            ${field.columnName} - ${field.fieldName}
        
    

    完整配置

     
    
    
    
       
       
            
          
          
          
          
          
            
          
          
          
            
          
    
    
    
    
          
          
             
             
             
             
             
             
             
          
    
          
          
             
             
             
             
             
             
          
    
    
          
          
             
             
             
             
             
             
             
          
    
    
            
            
                
                
                
            
    
    
    
          
          
    
    
    
    
          
             
             
          
    
          
          
          
          
          
          
    
    
    
          
             
             
             
             
          
       

     

    TK与mybatis-plus的区别

    Tk只对dao层进行了抽取封装,mp封装到了service层

    Tk:
    
    @Service
    public class TestServiceImpl extends BaseServiceImpl implements TestService {
        @Resource
        TestMapper mapper;
        @Override
        public int insert(Test input) {
    
            return mapper.insert(input);
        }
    }
    
    该Mapper extends tk的Mapper接口
    
    
    
    
    
    Mp:
    
    Service层操作
    
    public R> list(@Valid @ApiParam("查询对象")AccountLogQueryDto accountLogQueryDto, @ApiParam("分页对象")QPage qpage) {
        JcwlUser user = SecurityUtils.getUser();
        Account account = accountService.getOne(Wrappers.query()
                .lambda()
                .eq(Account::getUserId, user.getUserId())
                .eq(Account::getAccType, 1));
    
        return new R<>(new RPage<>());
    }
    
    accountService extends mp的IService接口,其实现类extends mp的ServiceImpl类
    
    (ServiceImpl, T> implements IService),
    
    ServiceImpl类有一个baseMapper变量可以直接使用
    
    
    
    
    
    Mapper层操作
    
    public AccountVo info(JcwlUser user) {
    
        Account account = baseMapper.selectOne(Wrappers.query()
                .lambda()
                .eq(Account::getUserId, user.getUserId())
                .eq(Account::getAccType, 1)
        );
    
        AccountVo accountVo = new AccountVo();
        //....
        return accountVo;
    }
    
    可以使用mp ServiceImpl类的baseMapper,也可以在自己的mapper里extends mp的BaseMapper接口

    发现bug

    tk中,service接口和mapper接口新增时不能同时起名insert,要么mapper接口的insert方法注释,要么改名

     

     

    PageHelper

    Tk的分页功能可以借助PageHelper

    官方下载:https://gitee.com/free/Mybatis_PageHelper

    配置

    Springboot引入依赖
    
    
    
        com.github.pagehelper
        pagehelper-spring-boot-starter
        1.2.13
    
    
    配置
    
    # 分页配置
    pagehelper:
      helper-dialect: mysql
      reasonable: true
      support-methods-arguments: true
      params: count=countSql
    
    使用
    
    PageHelper.startPage(pageNum,pageSize);//这行是重点,表示从pageNum页开始,每页pageSize条数据
    List list = toolsMapper.findAll();//紧跟着第一个select方法会被分页
    PageInfo pageInfo = new PageInfo(list);
    return ServerResponse.createBySuccess("查询成功",pageInfo);

    分页插件参数介绍

    1. helperDialect :分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect 属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:oracle , mysql , mariadb , sqlite , hsqldb , postgresql , db2 , sqlserver , informix , h2 , sqlserver2012 , derby特别注意:使用 SqlServer2012 数据库时,需要手动指定为 sqlserver2012 ,否则会使用 SqlServer2005 的方式进行分页。你也可以实现 AbstractHelperDialect ,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。

    2. offsetAsPageNum :默认值为 false ,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为true 时,会将 RowBounds 中的 offset 参数当成 pageNum 使用,可以用页码和页面大小两个参数进行分页。

    3. rowBoundsWithCount :默认值为 false ,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为 true 时,使用 RowBounds 分页会进行 count 查询。

    4. pageSizeZero :默认值为 false ,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit =0 就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型)。

    5. reasonable :分页合理化参数,默认值为 false 。当该参数设置为 true 时, pageNum<=0 时会查询第一页, pageNum>pages (超过总数时),会查询最后一页。默认 false 时,直接根据参数进行查询。

    6. params :为了支持 startPage(Object params) 方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable ,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero。

    7. supportMethodsArguments :支持通过 Mapper 接口参数来传递分页参数,默认值 false ,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTest 和ArgumentsObjTest 。

    8. autoRuntimeDialect :默认值为 false 。设置为 true 时,允许在运行时根据多数据源自动识别对应方言的分页 (不支持自动选择 sqlserver2012 ,只能使用 sqlserver ),用法和注意事项参考下面的场景五。

    9. closeConn :默认值为 true 。当使用运行时动态数据源或没有设置 helperDialect 属性自动获取数据库类型时,会自动获取一个数据库连接, 通过该属性来设置是否关闭获取的这个连接,默认 true 关闭,设置为false 后,不会关闭获取的连接,这个参数的设置要根据自己选择的数据源来决定。

     

     

     

    参考链接:

    https://gitee.com/free/Mapper/wikis

    https://blog.csdn.net/isea533/article/details/42102297

    https://blog.csdn.net/LONG_Yi_1994/article/details/94399645

    https://www.jianshu.com/p/2e15823f4ac4

     

你可能感兴趣的:(TK mapper与 PageHelper)