MyBatis Generator几种生成代码方式汇总
MyBatis Generator几种生成代码方式汇总
java代码+配置文件生成
- 编写配置文件
<?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>
- 编写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生成
- 将下面的百度网盘地址下载下来。并编写generator.xml文件,修改数据库账号密码等。
- 示例代码
<?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>
- 执行以下语句。
java -jar mybatis-generator-core-1.3.2.jar -configfile generator.xml -overwrite
- 将生成的文件拷贝到项目中。并删除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对象,包含了分页查询的所以信息数据,如下:
用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