天天看點

MyBatis三劍客MyBatis Generator幾種生成代碼方式彙總MyBatis-pluginMyBatis-pageHelper

MyBatis Generator幾種生成代碼方式彙總

  • MyBatis Generator幾種生成代碼方式彙總
    • java代碼+配置檔案生成
    • 純Java代碼+模闆生成
    • 指令行+XML生成
  • MyBatis-plugin
  • MyBatis-pageHelper
    • 第一步:添加依賴
    • 第二步:設定分頁

MyBatis Generator幾種生成代碼方式彙總

java代碼+配置檔案生成

  1. 編寫配置檔案
<?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>
    <context id="H2Tables" targetRuntime="MyBatis3">
        <plugin type="org.mybatis.generator.plugins.FluentBuilderMethodsPlugin" />
        <plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
        <plugin type="org.mybatis.generator.plugins.RowBoundsPlugin" />

        <jdbcConnection driverClass="org.h2.Driver"
                        connectionURL="jdbc:h2:mem:testdb"
                        userId="sa"
                        password="">
        </jdbcConnection>

        <javaModelGenerator targetPackage="geektime.spring.data.mybatis.model"
                            targetProject="./src/main/java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <sqlMapGenerator targetPackage="geektime.spring.data.mybatis.mapper"
                         targetProject="./src/main/resources/mapper">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <javaClientGenerator type="MIXEDMAPPER"
                             targetPackage="geektime.spring.data.mybatis.mapper"
                             targetProject="./src/main/java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <table tableName="t_coffee" domainObjectName="Coffee" >
            <generatedKey column="id" sqlStatement="CALL IDENTITY()" identity="true" />
            <columnOverride column="price" javaType="org.joda.money.Money" jdbcType="BIGINT"
                            typeHandler="geektime.spring.data.mybatis.handler.MoneyTypeHandler"/>
        </table>
    </context>
</generatorConfiguration>
           
  1. 編寫java代碼
private void generateArtifacts() throws Exception {
		List<String> warnings = new ArrayList<>();
		ConfigurationParser cp = new ConfigurationParser(warnings);
		Configuration config = cp.parseConfiguration(
				this.getClass().getResourceAsStream("/generatorConfig.xml"));
		DefaultShellCallback callback = new DefaultShellCallback(true);
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
		myBatisGenerator.generate(null);
	}
           

純Java代碼+模闆生成

public class AutoCodeGenerator {
    // JDBC配置,請修改為你項目的實際配置,必須增加 nullCatalogMeansCurrent=true配置,否則生成的實體和xml檔案無法正常映射主鍵
    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&nullCatalogMeansCurrent=true";
    private static final String JDBC_USERNAME = "admin";
    private static final String JDBC_PASSWORD = "admin";
    private static final String JDBC_DIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
    
    private static final String PROJECT_PATH = "D:\\admin";
    // Model,Mapper所在項目的磁盤目錄
    private static final String DATABASE_PROJECT_PATH = "D:\\database";
    // 模闆位置
    private static final String TEMPLATE_FILE_PATH = "generator\\template";
    // java檔案路徑
    private static final String JAVA_PATH = "/src/main/java";
    // 資源檔案路徑
    private static final String RESOURCES_PATH = "/src/main/resources";
    // 生成的Service存放路徑
    private static final String PACKAGE_PATH_SERVICE = packageConvertPath(ProjectConstant.SERVICE_PACKAGE);
    // 生成的Service實作存放路徑
    private static final String PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(ProjectConstant.SERVICE_IMPL_PACKAGE);
    // 生成的Controller存放路徑
    private static final String PACKAGE_PATH_CONTROLLER = packageConvertPath(ProjectConstant.CONTROLLER_PACKAGE);

    // @author
    private static final String AUTHOR = "auto";
    // @date
    private static final String DATE = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
    private static final boolean isRestful = true;
    private static boolean overwrite = false;

    public static void main(final String[] args) {
        final Scanner scanner = new Scanner(System.in);
        System.out.print("可能已存在相關檔案,是否覆寫?y/n:");
        if (scanner.next().equals("y")) {
            overwrite = true;
        }
        genCode("table_name");
        //genCodeByCustomModelName("輸入表名","輸入自定義Model名稱");
    }

    /**
     * 通過資料表名稱生成代碼,Model 名稱通過解析資料表名稱獲得,下劃線轉大駝峰的形式。
     * 如輸入表名稱 "t_user_detail" 将生成 TUserDetail、TUserDetailMapper、TUserDetailService ...
     *
     * @param tableNames 資料表名稱...
     */
    private static void genCode(final String... tableNames) {
        for (final String tableName : tableNames) {
            genCodeByCustomModelName(tableName, null);
        }
    }

    /**
     * 通過資料表名稱,和自定義的 Model 名稱生成代碼
     * 如輸入表名稱 "t_user_detail" 和自定義的 Model 名稱 "sysUser" 将生成 sysUser、UserMapper、UserService ...
     *
     * @param tableName 資料表名稱
     * @param modelName 自定義的 Model 名稱
     */
    private static void genCodeByCustomModelName(final String tableName, final String modelName) {
        genModelAndMapper(tableName, modelName);
        genService(tableName, modelName);  //TODO;去除Service的生成
        genController(tableName, modelName); //TODO;去除Service的生成
    }


    private static void genModelAndMapper(final String tableName, String modelName) {
        final Context context = new Context(ModelType.FLAT);
        context.setId("Potato");
        context.setTargetRuntime("MyBatis3Simple");
        context.addProperty(PropertyRegistry.CONTEXT_BEGINNING_DELIMITER, "`");
        context.addProperty(PropertyRegistry.CONTEXT_ENDING_DELIMITER, "`");

        final JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
        jdbcConnectionConfiguration.setConnectionURL(JDBC_URL);
        jdbcConnectionConfiguration.setUserId(JDBC_USERNAME);
        jdbcConnectionConfiguration.setPassword(JDBC_PASSWORD);
        jdbcConnectionConfiguration.setDriverClass(JDBC_DIVER_CLASS_NAME);
        context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);

        final PluginConfiguration pluginConfiguration = new PluginConfiguration();
        pluginConfiguration.setConfigurationType("tk.mybatis.mapper.generator.MapperPlugin");
        pluginConfiguration.addProperty("mappers", ProjectConstant.MAPPER_INTERFACE_REFERENCE);
        context.addPluginConfiguration(pluginConfiguration);

        final JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
        javaModelGeneratorConfiguration.setTargetProject(DATABASE_PROJECT_PATH + JAVA_PATH);
        javaModelGeneratorConfiguration.setTargetPackage(ProjectConstant.MODEL_PACKAGE);
        context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);

        final SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
        sqlMapGeneratorConfiguration.setTargetProject(DATABASE_PROJECT_PATH + RESOURCES_PATH);
        sqlMapGeneratorConfiguration.setTargetPackage(ProjectConstant.XML_MAPPER_PACKAGE);
        context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);

        final JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
        javaClientGeneratorConfiguration.setTargetProject(DATABASE_PROJECT_PATH + JAVA_PATH);
        javaClientGeneratorConfiguration.setTargetPackage(ProjectConstant.MAPPER_PACKAGE);
        javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
        context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);

        final TableConfiguration tableConfiguration = new TableConfiguration(context);
        tableConfiguration.setTableName(tableName);
        //如果資料庫連接配接沒有增加 nullCatalogMeansCurrent=true配置,則必須要配置Catalog,否則生成的實體和xml檔案無法正常映射主鍵
        //tableConfiguration.setCatalog("yaue");
        if (StringUtils.isNotEmpty(modelName)) {
            tableConfiguration.setDomainObjectName(modelName);
        }
        tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null));
        context.addTableConfiguration(tableConfiguration);

        final List<String> warnings;
        final MyBatisGenerator generator;
        try {
            final Configuration config = new Configuration();
            config.addContext(context);
            config.validate();

            final DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            warnings = new ArrayList<>();
            generator = new MyBatisGenerator(config, callback, warnings);
            generator.generate(null);
        } catch (final Exception e) {
            throw new RuntimeException("生成 Model和 Mapper 失敗", e);
        }

        if (generator.getGeneratedJavaFiles().isEmpty() || generator.getGeneratedXmlFiles().isEmpty()) {
            throw new RuntimeException("生成 Model 和 Mapper 失敗:" + warnings);
        }
        if (StringUtils.isEmpty(modelName)) {
            modelName = tableNameConvertUpperCamel(tableName);
        }
        System.out.println(modelName + ".java 生成成功");
        System.out.println(modelName + "Mapper.java 生成成功");
        System.out.println(modelName + "Mapper.xml 生成成功");
    }

    private static void genService(final String tableName, final String modelName) {
        try {
            final freemarker.template.Configuration cfg = getConfiguration();

            final Map<String, Object> data = new HashMap<>();
            data.put("date", DATE);
            data.put("author", AUTHOR);
            final String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
            data.put("modelNameUpperCamel", modelNameUpperCamel);
            data.put("modelNameLowerCamel", tableNameConvertLowerCamel(tableName));
            data.put("servicePackage", ProjectConstant.SERVICE_PACKAGE);
            data.put("serviceImplPackage", ProjectConstant.SERVICE_IMPL_PACKAGE);
            data.put("modelPackage", ProjectConstant.MODEL_PACKAGE);
            data.put("mapperPackage", ProjectConstant.MAPPER_PACKAGE);

            final File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE + modelNameUpperCamel + "Service.java");
            if (!file.getParentFile().exists()) {
                final boolean isMake = file.getParentFile().mkdirs();
                if (!isMake) {
                    throw new IOException("建立檔案失敗");
                }
            }
            cfg.getTemplate("service.ftl").process(data,
                    new FileWriter(file));
            System.out.println(modelNameUpperCamel + "Service.java 生成成功");

            final File file1 = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE_IMPL + modelNameUpperCamel + "ServiceImpl.java");
            if (!file1.getParentFile().exists()) {
                final boolean isMake = file1.getParentFile().mkdirs();
                if (!isMake) {
                    throw new IOException("建立檔案失敗");
                }
            }
            cfg.getTemplate("service-impl.ftl").process(data,
                    new FileWriter(file1));
            System.out.println(modelNameUpperCamel + "ServiceImpl.java 生成成功");
        } catch (final Exception e) {
            throw new RuntimeException("生成 Service 失敗,", e);
        }
    }

    private static void genController(final String tableName, final String modelName) {
        try {
            final freemarker.template.Configuration cfg = getConfiguration();

            final Map<String, Object> data = new HashMap<>();
            data.put("date", DATE);
            data.put("author", AUTHOR);
            final String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
            data.put("baseRequestMapping", modelNameConvertMappingPath(modelNameUpperCamel));
            data.put("modelNameUpperCamel", modelNameUpperCamel);
            data.put("modelNameLowerCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, modelNameUpperCamel));
            data.put("controllerPackage", ProjectConstant.CONTROLLER_PACKAGE);
            data.put("servicePackage", ProjectConstant.SERVICE_PACKAGE);
            data.put("modelPackage", ProjectConstant.MODEL_PACKAGE);

            final File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_CONTROLLER + modelNameUpperCamel + "Controller.java");
            if (!file.getParentFile().exists()) {
                final boolean isMake = file.getParentFile().mkdirs();
                if (!isMake) {
                    throw new IOException("建立檔案失敗");
                }
            }

            if (isRestful) {
                cfg.getTemplate("controller-restful.ftl").process(data, new FileWriter(file));
            } else {
                cfg.getTemplate("controller.ftl").process(data, new FileWriter(file));
            }
            System.out.println(modelNameUpperCamel + "Controller.java 生成成功");
        } catch (final Exception e) {
            throw new RuntimeException("生成 Controller 失敗,", e);
        }

    }

    private static freemarker.template.Configuration getConfiguration() throws IOException {
        final freemarker.template.Configuration cfg = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_23);
        cfg.setDirectoryForTemplateLoading(new File(TEMPLATE_FILE_PATH));
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        return cfg;
    }

    private static String tableNameConvertLowerCamel(final String tableName) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName.toLowerCase());
    }

    private static String tableNameConvertUpperCamel(final String tableName) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase());

    }

    private static String tableNameConvertMappingPath(String tableName) {
        tableName = tableName.toLowerCase();//相容使用大寫的表名
        return "/" + (tableName.contains("_") ? tableName.replaceAll("_", "/") : tableName);
    }

    private static String modelNameConvertMappingPath(final String modelName) {
        final String tableName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, modelName);
        return tableNameConvertMappingPath(tableName);
    }

    private static String packageConvertPath(final String packageName) {
        return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
    }

}

           

不同模闆

//controller.ftl
package ${controllerPackage};

import ${modelPackage}.${modelNameUpperCamel};
import ${servicePackage}.${modelNameUpperCamel}Service;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
 * description:
 * author ${author}
 * date ${date}
 */
@RestController
@RequestMapping("${baseRequestMapping}")
public class ${modelNameUpperCamel}Controller {
    @Resource
    private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service;

}

//controller-restful.ftl
package ${controllerPackage};

import ${modelPackage}.${modelNameUpperCamel};
import ${servicePackage}.${modelNameUpperCamel}Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
 * description:
 * author ${author}
 * date ${date}
 */
@RestController
@RequestMapping("${baseRequestMapping}")
public class ${modelNameUpperCamel}Controller {
    @Resource
    private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service;

}
//service.ftl
package ${servicePackage};

import ${modelPackage}.${modelNameUpperCamel};
import com.test.service.Service;

/**
 * description:
 * author ${author}
 * date ${date}
 */
public interface ${modelNameUpperCamel}Service extends Service<${modelNameUpperCamel}> {
}

//service-impl.ftl
package ${serviceImplPackage};

import ${mapperPackage}.${modelNameUpperCamel}Mapper;
import ${modelPackage}.${modelNameUpperCamel};
import ${servicePackage}.${modelNameUpperCamel}Service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @description:
 * @author ${author}
 * @date ${date}
 */
@Service
public class ${modelNameUpperCamel}ServiceImpl extends AbstractService<${modelNameUpperCamel}> implements ${modelNameUpperCamel}Service {
    @Resource
    private ${modelNameUpperCamel}Mapper ${modelNameLowerCamel}Mapper;

}

           

指令行+XML生成

  1. 将下面的百度網盤位址下載下傳下來。并編寫generator.xml檔案,修改資料庫賬号密碼等。
    MyBatis三劍客MyBatis Generator幾種生成代碼方式彙總MyBatis-pluginMyBatis-pageHelper
  2. 示例代碼
<?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>
	<!-- 資料庫驅動包位置 -->
	<!-- <classPathEntry location="D:\software\lib\mysql-connector-java-5.1.21.jar" /> -->
	<classPathEntry location="C:\oracle\product\10.2.0\db_1\jdbc\lib\ojdbc14.jar" />
	<context id="DB2Tables" targetRuntime="MyBatis3">
		<commentGenerator>
			<property name="suppressAllComments" value="true" />
		</commentGenerator>
		<!-- 資料庫連結URL、使用者名、密碼 -->
		<!-- <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/sy" userId="sypro" password="sypro"> -->
		<jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@localhost:1521:orcl" userId="msa" password="msa">
		</jdbcConnection>
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>
		<!-- 生成模型的包名和位置 -->
		<javaModelGenerator targetPackage="sy.model" targetProject="D:\mybatis\src">
			<property name="enableSubPackages" value="true" />
			<property name="trimStrings" value="true" />
		</javaModelGenerator>
		<!-- 生成的映射檔案包名和位置 -->
		<sqlMapGenerator targetPackage="sy.mapping" targetProject="D:\mybatis\src">
			<property name="enableSubPackages" value="true" />
		</sqlMapGenerator>
		<!-- 生成DAO的包名和位置 -->
		<javaClientGenerator type="XMLMAPPER" targetPackage="sy.dao" targetProject="D:\study\mybatis\src">
			<property name="enableSubPackages" value="true" />
		</javaClientGenerator>
		<!-- 要生成那些表(更改tableName和domainObjectName就可以) -->
		<table tableName="tbug" domainObjectName="Bug" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
		<table tableName="tmenu" domainObjectName="Menu" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
		<table tableName="tonline" domainObjectName="Online" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
		<table tableName="tresource" domainObjectName="Resource" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
		<table tableName="trole" domainObjectName="Role" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
		<table tableName="trole_tresource" domainObjectName="RoleResource" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
		<table tableName="tuser" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
		<table tableName="tuser_trole" domainObjectName="UserRole" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" />
	</context>
</generatorConfiguration>
           
  1. 執行以下語句。
java -jar mybatis-generator-core-1.3.2.jar -configfile generator.xml -overwrite
           
  1. 将生成的檔案拷貝到項目中。并删除get,set方法,改成@Data注解;并增加@Builder注解。

連結:https://pan.baidu.com/s/1TrjcueIu0wKdlGxflPH1wg

提取碼:771i

MyBatis-plugin

MyBatis-plugin是可以快速定位接口對應的sql語句位置的一款插件。

安裝過程:點選settings --> Plugins --> Marketplace --> 搜尋Free MyBatis plugin --> install --> restart IDE。

在MyBatis-plugin沒有出現的時候,一般都是ctrl+F來定位接口和sql位置,有時候會出現多個比對選項,需要一一對比,出錯率還是挺高的,但是使用MyBatis-plugin既可以大大規避錯誤的風險。

MyBatis-pageHelper

第一步:添加依賴

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.5</version>
</dependency>
           

第二步:設定分頁

//[pageNum, pageSize]  頁碼  每頁顯示數量
PageHelper.startPage(curPage,pageSize);
PageInfo<Order> pageInfo = new PageInfo<>(orderMapper.findAll());
           

在需要執行查詢之前,這是分頁資料(curPage&pageSize)。會傳回一個PageInfo對象,包含了分頁查詢的是以資訊資料,如下:

MyBatis三劍客MyBatis Generator幾種生成代碼方式彙總MyBatis-pluginMyBatis-pageHelper

用pageHelper插件,它會攔截我們寫的sql語句,自己重新包裝一層,在後面添加limit。是以當資料量大的時候,就會出現limit深度分頁問題,解決辦法同深度分頁的方式一樣,利用索引的優勢,将SQL語句改寫成先滿足條件的id,然後根據id進行查找最近的分頁條數。如下所示。

//用pageHelper的查詢
select * from (select * from account where age >= 20)where limit 100,10;
//改寫後的深度分頁
SELECT * FROM account WHERE  id >= (SELECT id FROM account WHERE age = 20 ORDER BY id LIMIT 10000, 1) LIMIT 10