集成和使用mybatis生成器

Java小卷
• 阅读 479

前面我们搭建好了本地对持久层的单元测试环境。当我们自己实现dao层的一些关级联查询或者批量的写库更新库的操作时,要验证逻辑的正确性,就可以写一些dao层的单元测试来验证。

而大部分情况下针对单表的curd操作,我们可以用mybatis生成器帮我们生成相应的mapper,直接用即可。不多废话,下面开干!

编写gradle脚本

现在我们将编写一个新的gradle脚本来使用生成器插件,并创建相应的生成任务。

集成和使用mybatis生成器

build.gradle中引入这个脚本文件即可。

...

apply from: 'mbgen.gradle'

下面我们编写生成脚本,首先声明一个生成器的配置:

configurations {
    mybatisGenerator
}

基于这个配置类型,我们引入mybatis生成器需要的依赖:

dependencies {
    // 生成器工具
    mybatisGenerator 'org.mybatis.generator:mybatis-generator-core:1.4.1'
    // 生成器连接h2数据库
    mybatisGenerator 'com.h2database:h2:1.4.200'
}

这个文件先写到这里,接下来我们关注生成器的相关配置。

抽取生成器配置

对用户来说,用户无需关心生成器本身的配置,而应该是跟项目生成的路径,生成的名称等相关的设置。因此,我们自定义这样的属性配置文件:

集成和使用mybatis生成器

# 生成器连接数据源配置
mybatis.generator.dataSource.driverClassName=org.h2.Driver
mybatis.generator.dataSource.username=sa
mybatis.generator.dataSource.password=
mybatis.generator.genUrl=jdbc:h2:tcp://localhost/~/db_juan_mall
# 生成目标,mybatis的特性版本
mybatis.generator.target-runtime=MyBatis3DynamicSql
#mybatis.generator.target-runtime=MyBatis3
# 生成实体类所在的包
mybatis.generator.model.package=com.xiaojuan.boot.dao.generated.model
# 生成mapper所在的包
mybatis.generator.mapper.package=com.xiaojuan.boot.dao.generated.mapper
# 生成xml形式的mapper文件所在的资源包路径
mybatis.generator.mapper.xml=mapper.generated
# 要匹配的表前缀
mybatis.generator.table.prefix=Tb
# 要去除的前缀
mybatis.generator.table.prefix.clear=Tb

友情提示

在properties文件中出现中文,idea默认的编码不支持,我们把properties文件全局设为UTF-8格式

集成和使用mybatis生成器 然后我们再把生成器核心的配置文件放进来:

集成和使用mybatis生成器

这个文件内容如下,其中需要外部提供配置的地方我们采用了${...}的形式,这个文件对用户来说是不用关心的,有特殊需要再修改这个文件里的配置:

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

<generatorConfiguration>

    <!-- MyBatis3、MyBatis3DynamicSql -->
    <context id="default" targetRuntime="${mybatis.generator.target-runtime}">

        <!-- optional,旨在创建class时,对注释进行控制 -->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!--jdbc的数据库连接 -->
        <jdbcConnection
                driverClass="${mybatis.generator.dataSource.driverClassName}"
                connectionURL="${mybatis.generator.genUrl}"
                userId="${mybatis.generator.dataSource.username}"
                password="${mybatis.generator.dataSource.password}">
        </jdbcConnection>


        <!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl">
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>


        <!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
            targetPackage     指定生成的model生成所在的包名
            targetProject     指定在该项目下所在的路径
        -->
        <!--<javaModelGenerator targetPackage="com.mmall.pojo" targetProject=".\src\main\java">-->
        <javaModelGenerator targetPackage="${mybatis.generator.model.package}" targetProject="./src/main/java">
            <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>
            <!-- 是否对model添加 构造函数 -->
            <property name="constructorBased" value="true"/>
            <!-- 是否对类CHAR类型的列的数据进行trim操作 -->
            <property name="trimStrings" value="true"/>
            <!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 -->
            <property name="immutable" value="false"/>
        </javaModelGenerator>

        <!--mapper映射文件生成所在的目录 为每一个数据库的表生成对应的SqlMap文件 -->
        <!--<sqlMapGenerator targetPackage="mappers" targetProject=".\src\main\resources">-->
        <sqlMapGenerator targetPackage="${mybatis.generator.mapper.xml}" targetProject="./src/main/resources">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- 客户端代码,生成易于使用的针对Model对象和XML配置文件 的代码
                type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper对象
                type="MIXEDMAPPER",生成基于注解的Java Model 和相应的Mapper对象
                type="XMLMAPPER",生成SQLMap XML文件和独立的Mapper接口
        -->

        <!-- targetPackage:mapper接口dao生成的位置 -->
        <!--<javaClientGenerator type="XMLMAPPER" targetPackage="com.mmall.dao" targetProject=".\src\main\java">-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="${mybatis.generator.mapper.package}" targetProject="./src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>

        <table tableName="${mybatis.generator.table.prefix}_%">
            <generatedKey column="id" sqlStatement="MySql" identity="true"/>
            <!-- 这行配置存在bug 生成的model多个单词都小写了 -->
            <domainObjectRenamingRule searchString="^${mybatis.generator.table.prefix.clear}" replaceString="" />
<!--            <columnOverride column="detail" javaType="java.lang.String" jdbcType="VARCHAR"/>-->
<!--            <columnOverride column="sub_images" javaType="java.lang.String" jdbcType="VARCHAR" />-->
        </table>

    </context>
</generatorConfiguration>

获取属性文件

接下来,我们再回到mbgen.gradle文件的编写上来,我们写一个方法来加载生成器属性配置文件:

def getDbProperties = {
    def properties = new Properties()
    file("src/main/resources/mbgen.properties").withInputStream { inputStream ->
        properties.load(inputStream)
    }
    properties
}

定义ant任务使用生成器

最后一步,我们借助ant工具来完成属性的填充,并调用生成器工具来完成生成工作。写一个ant任务:

task mybatisGenerate {
    def properties = getDbProperties()
//    ant.properties['targetProject'] = projectDir.path
    ant.properties['mybatis.generator.dataSource.driverClassName'] = properties.getProperty("mybatis.generator.dataSource.driverClassName")
    ant.properties['mybatis.generator.dataSource.username'] = properties.getProperty("mybatis.generator.dataSource.username")
    ant.properties['mybatis.generator.dataSource.password'] = properties.getProperty("mybatis.generator.dataSource.password")
    ant.properties['mybatis.generator.genUrl'] = properties.getProperty("mybatis.generator.genUrl")
    ant.properties['mybatis.generator.target-runtime'] = properties.getProperty("mybatis.generator.target-runtime")
    ant.properties['mybatis.generator.model.package'] = properties.getProperty("mybatis.generator.model.package")
    ant.properties['mybatis.generator.mapper.package'] = properties.getProperty("mybatis.generator.mapper.package")
    ant.properties['mybatis.generator.mapper.xml'] = properties.getProperty("mybatis.generator.mapper.xml")
    ant.properties['mybatis.generator.table.prefix'] = properties.getProperty("mybatis.generator.table.prefix")
    ant.properties['mybatis.generator.table.prefix.clear'] = properties.getProperty("mybatis.generator.table.prefix.clear")

    ant.taskdef(
            name: 'mbgenerator',
            classname: 'org.mybatis.generator.ant.GeneratorAntTask',
            classpath: configurations.mybatisGenerator.asPath
    )

    ant.mbgenerator(overwrite: true,
            configfile: projectDir.path + '/src/main/resources/generatorConfig.xml', verbose: true) {
        propertyset {
//            propertyref(name: 'targetProject')
            propertyref(name: 'mybatis.generator.dataSource.driverClassName')
            propertyref(name: 'mybatis.generator.dataSource.username')
            propertyref(name: 'mybatis.generator.dataSource.password')
            propertyref(name: 'mybatis.generator.genUrl')
            propertyref(name: 'mybatis.generator.target-runtime')
            propertyref(name: 'mybatis.generator.model.package')
            propertyref(name: 'mybatis.generator.mapper.package')
            propertyref(name: 'mybatis.generator.mapper.xml')
            propertyref(name: 'mybatis.generator.table.prefix')
            propertyref(name: 'mybatis.generator.table.prefix.clear')
        }
    }
}

执行生成器

当我们刷新gradle配置后,就执行了生成任务,可以看到生成的结果:

集成和使用mybatis生成器

同时我们在gradle工具箱中也可以看到生成的任务,以后双击就可以重新生成并覆盖了。

集成和使用mybatis生成器

友情提示

当我们无需重新生成时,可以把apply from: 'mbgen.gradle'注释掉,不然每次刷新gradle配置,都要执行一次。

使用生成的api

因为我们采用的是mybatis3的dynamic sql特性,因此不再生成传统的xml形式的mapper文件了。

关于这个特性的语法可以参考:https://mybatis.org/mybatis-dynamic-sql/docs/mybatis3.html

为此我们还要引入一个mybatis dynamic sql的依赖:

dependencies {
    ...
    implementation 'org.mybatis.dynamic-sql:mybatis-dynamic-sql:1.4.0'
}

在编写一个单元测试来使用生成器生成的mapper前,我们先配置下生成器mapper的日志输出:

application.yml

logging:
  level:
    ...
    com.xiaojuan.boot.dao.generated.mapper: trace

然后将原来写的model和mapper删掉,因为生成器帮我们生成了这些,category-mapper.xml也删除。

集成和使用mybatis生成器

最后是我们的单元测试:

package com.xiaojuan.boot.dao.mapper;

import ...

import static org.junit.jupiter.api.Assertions.*;

import static com.xiaojuan.boot.dao.generated.mapper.CategoryDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*;

@Transactional // 确保每个单元测试后数据会回滚,实现单元测试数据的隔离
@SpringBootTest
public class CategoryMapperTest {

    @Resource
    private CategoryMapper categoryMapper;

    @Test
    public void testCountAll() {
        long count = categoryMapper.count(CountDSLCompleter.allRows());
        assertEquals(3, count);
    }

    @Test
    public void testListTopLevelCategories() {
        List<Category> categories = categoryMapper.select(c -> c.where(level, isEqualTo((byte)1)));
        assertEquals(1, categories.size());
    }
}

测试ok!

集成和使用mybatis生成器

点赞
收藏
评论区
推荐文章

暂无数据

Java小卷
Java小卷
Lv1
谁家玉笛暗飞声,散入春风满洛城。
文章
0
粉丝
1
获赞
0
热门文章

暂无数据