SpringBoot集成Mybatis-Plus代码生成工具

news/2024/7/4 0:51:35 标签: java, generator, mybatis, spring boot, mysql

点击上方“猿芯”,选择“设为星标

后台回复"1024",有份惊喜送给面试的你

前言

Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。这是官方给的定义,关于mybatis-plus的更多介绍及特性,可以参考mybatis-plus官网。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA。

SpringBoot集成Mybatis-Plus在这里不贴代码了,网上有很多的例子。现在介绍集成Mybatis-Plus的代码生成工具。

版本

JDK:1.8

springboot:2.0.0.RELEASE

mybatis-plus-boot-starter:3.0.7.1

mybatis-plus-generator:3.0.7.1

依赖

这里只贴了mybatis-plus-generator的相关的依赖。

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.7.1</version>
        </dependency>
     <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.0.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-configuration2</artifactId>
            <version>2.2</version>
        </dependency>

配置文件

generate.properties

############################数据源配置############################jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://xxxxx/test?useUnicode=true&characterEncoding=utf-8&useSSL=falsejdbc.username=xxxx
jdbc.password=xxxxx############################项目位置和表的配置#############################其他实体类的路径-修改自己的项目中的位置genetator_path=D:/workspace/test_workspace/common/src/main/java#Mybatis的xml文件路径-修改自己的项目中的位置xml_path=D:/workspace/test_workspace/common/src/main/resources/mapper##################server,mapper,model包的配置##############################server_package=com.test.service
mapper_package=com.test.dao
model_package=com.test.domain.bo##################代码注释的作者,可修改为自己,不修改为默认##############################author=my-generate##################表配置,修改为数据中的表名称##############################table_name=t_test

工具类

import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.generator.AutoGenerator;import com.baomidou.mybatisplus.generator.InjectionConfig;import com.baomidou.mybatisplus.generator.config.DataSourceConfig;import com.baomidou.mybatisplus.generator.config.FileOutConfig;import com.baomidou.mybatisplus.generator.config.GlobalConfig;import com.baomidou.mybatisplus.generator.config.PackageConfig;import com.baomidou.mybatisplus.generator.config.StrategyConfig;import com.baomidou.mybatisplus.generator.config.TemplateConfig;import com.baomidou.mybatisplus.generator.config.po.TableInfo;import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;import java.io.File;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import org.apache.commons.configuration2.Configuration;import org.apache.commons.configuration2.PropertiesConfiguration;import org.apache.commons.configuration2.ex.ConfigurationException;public class MpGeneratorUtil {	/**
	 * 请不要随意改动方法的代码
	 */
	public static void generateCode() {		// 读取配置文件
		Configuration config = getConfig();		// 全局配置
		GlobalConfig globalConfig = new GlobalConfig();
		globalConfig.setActiveRecord(false)
				.setAuthor(config.getString("author"))
				.setOutputDir(config.getString("genetator_path"))
				.setFileOverride(true)
				.setEnableCache(false)// XML 二级缓存
				.setBaseResultMap(true)// XML ResultMap
				.setBaseColumnList(true)// XML columList
				.setServiceImplName("%sServiceImpl")
				.setServiceName("%sService")
				.setIdType(IdType.INPUT);		// 设置数据源
		DataSourceConfig dataSourceConfig = new DataSourceConfig();
		dataSourceConfig.setDbType(DbType.MYSQL)
				.setUrl(config.getString("jdbc.url"))
				.setUsername(config.getString("jdbc.username"))
				.setPassword(config.getString("jdbc.password"))
				.setDriverName(config.getString("jdbc.driverClassName"));		// 策略配置
		StrategyConfig strategyConfig = new StrategyConfig();
		strategyConfig				//.setCapitalMode(true) // 全局大写命名
				// .setTablePrefix("") // 设置表前缀
				.setEntityLombokModel(true)
		    .setRestControllerStyle(true)				//.setSuperEntityClass(config.getString("supper_entity")) //父entity
				.setNaming(NamingStrategy.underline_to_camel)
		    .setColumnNaming(NamingStrategy.underline_to_camel)
				.setInclude(config.getString("table_name"));// 修改替换成你需要的表名,多个表名传数组
		// strategyConfig.entityTableFieldAnnotationEnable(true); // 是否生成实体时,生成字段注解

		// 包配置
		PackageConfig packageConfig = new PackageConfig();		// 为了方便各个层级自定义包。将parent设置为空。在各个子层级set全路径
		String parentPackage = config.getString("server_package");		String modelPackage = config.getString("model_package");		String mapperPackage = config.getString("mapper_package");
		packageConfig.setParent(null)				//.setController(parentPackage + "controller")
				.setService(parentPackage)
				.setServiceImpl(parentPackage + ".impl")
				.setMapper(mapperPackage)
				.setEntity(modelPackage);		// 注入自定义配置,可以根据自己需求实现
		InjectionConfig cfg = new InjectionConfig() {			@Override
			public void initMap() {				// to do nothing
			}
		};		// 自定义 xx.xml 生成
		List<FileOutConfig> focList = new ArrayList<>();		// 调整 xml 生成目录演示
		focList.add(new FileOutConfig("/templates/mapper.xml.vm") {			@Override
			public String outputFile(TableInfo tableInfo) {				return config.getString("xml_path") + File.separator +
						tableInfo.getEntityName() + "Mapper.xml";
			}
		});
		cfg.setFileOutConfigList(focList);		// 关闭默认 xml 生成,调整生成 至 根目录
		TemplateConfig tc = new TemplateConfig();
		tc.setXml(null).setController(null);		new AutoGenerator().setGlobalConfig(globalConfig)
				.setDataSource(dataSourceConfig)
				.setStrategy(strategyConfig)
				.setPackageInfo(packageConfig)
				.setTemplate(tc)
				.setCfg(cfg)
				.setTemplateEngine(new MyVelocityTemplateEngine()) //自定义模板引擎
				.execute();

	}	/**
	 * 获取配置信息
	 */
	public static Configuration getConfig() {		try {
			Configuration config = new PropertiesConfiguration();
			InputStreamReader reader = new InputStreamReader(
					Thread.currentThread().getContextClassLoader()
							.getResourceAsStream("config/generate.properties"), "UTF-8");
			((PropertiesConfiguration) config).read(reader);			return config;
		} catch (ConfigurationException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		return null;
	}
}

这里使用的Velocity模板,也可以使用freemarker模板。

自定义模板引擎:

import com.baomidou.mybatisplus.generator.config.ConstVal;import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;import com.baomidou.mybatisplus.generator.config.po.TableInfo;import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;import java.io.BufferedWriter;import java.io.FileOutputStream;import java.io.OutputStreamWriter;import java.util.Map;import java.util.Properties;import org.apache.commons.lang.StringUtils;import org.apache.velocity.Template;import org.apache.velocity.VelocityContext;import org.apache.velocity.app.Velocity;import org.apache.velocity.app.VelocityEngine;/**
 * 自定义模板引擎
 */public class MyVelocityTemplateEngine extends AbstractTemplateEngine {	private static final String DOT_VM = ".vm";	private VelocityEngine velocityEngine;	@Override
	public MyVelocityTemplateEngine init(ConfigBuilder configBuilder) {		super.init(configBuilder);		if (null == velocityEngine) {
			Properties p = new Properties();
			p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
			p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
			p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
			p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
			p.setProperty("file.resource.loader.unicode", "true");
			velocityEngine = new VelocityEngine(p);
		}		return this;
	}	@Override
	public void writer(Map<String, Object> objectMap, String templatePath, String outputFile)
			throws Exception {		if (StringUtils.isEmpty(templatePath)) {			return;
		}		// 给生成的entity文件修改为entityVo
		/*if (templatePath.matches(".*entity\\.java\\.vm$")) {
			outputFile = outputFile.replace(".java", "Vo.java");
		}*/
		Template template = velocityEngine.getTemplate(templatePath, ConstVal.UTF8);
		FileOutputStream fos = new FileOutputStream(outputFile);
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, ConstVal.UTF8));
		template.merge(new VelocityContext(objectMap), writer);
		writer.close();
		logger.debug("模板:" + templatePath + ";  文件:" + outputFile);
	}	/**
	 * 自定义获取table信息表。对entity值扩展为entity+Vo
	 */
	@Override
	public Map<String, Object> getObjectMap(TableInfo tableInfo) {
		Map<String, Object> map = super.getObjectMap(tableInfo);		//将实体类加上VO后缀
		//map.replace("entity", map.get("entity").toString() + "Vo");
		return map;
	}	@Override
	public String templateFilePath(String filePath) {		if (null == filePath || filePath.contains(DOT_VM)) {			return filePath;
		}
		StringBuilder fp = new StringBuilder();
		fp.append(filePath).append(DOT_VM);		return fp.toString();
	}
}

模板文件

模板文件位于
src/main/resource/templates目录下,主要有:

controller.java.vm

entity.java.vm

mapper.java.vm

mapper.xml.vm

service.java.vm

serviceImpl.java.vm

根据模板文件定义的模板实现相应的类

controller.java.vm

package ${package.Controller};import org.springframework.web.bind.annotation.RequestMapping;#if(${restControllerStyle})import org.springframework.web.bind.annotation.RestController;#elseimport org.springframework.stereotype.Controller;#end#if(${superControllerClassPackage})import ${superControllerClassPackage};#end/**
 * <p>
 * $!{table.comment} 前端控制器
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */#if(${restControllerStyle})@RestController#else@Controller#end@RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end")#if(${kotlin})class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end#else#if(${superControllerClass})public class ${table.controllerName} extends ${superControllerClass} {#elsepublic class ${table.controllerName} {#end}#end

entity.java.vm

package ${package.Entity};#foreach($pkg in ${table.importPackages})import ${pkg};#end#if(${entityLombokModel})import lombok.Data;#if(${superEntityClass})import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;#end#endimport com.baomidou.mybatisplus.annotation.TableName;
/**
 * <p>
 * $!{table.comment}
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */#if(${entityLombokModel})@Data#if(${superEntityClass})@EqualsAndHashCode(callSuper = true)#end#end@TableName("${table.name}")#if(${superEntityClass})public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end {#elseif(${activeRecord})public class ${entity} extends Model<${entity}> {#elsepublic class ${entity} implements Serializable {#end

    private static final long serialVersionUID = 1L;## ----------  BEGIN 字段循环遍历  ----------#foreach($field in ${table.fields})#if(${field.keyFlag})#set($keyPropertyName=${field.propertyName})#end#if("$!field.comment" != "")
    /**
     * ${field.comment}
     */#end#if(${field.keyFlag})## 主键#if(${field.keyIdentityFlag})
    @TableId(value = "${field.name}", type = IdType.AUTO)#elseif(!$null.isNull(${idType}) && "$!idType" != "")
    @TableId(value = "${field.name}", type = IdType.${idType})#elseif(${field.convert})
    @TableId("${field.name}")#end## 普通字段#elseif(${field.fill})## -----   存在字段填充设置   -----#if(${field.convert})
    @TableField(value = "${field.name}", fill = FieldFill.${field.fill})#else
    @TableField(fill = FieldFill.${field.fill})#end#elseif(${field.convert})
    @TableField("${field.name}")#end## 乐观锁注解#if(${versionFieldName}==${field.name})
    @Version#end## 逻辑删除注解#if(${logicDeleteFieldName}==${field.name})
    @TableLogic#end
    private ${field.propertyType} ${field.propertyName};#end## ----------  END 字段循环遍历  ----------#if(!${entityLombokModel})#foreach($field in ${table.fields})#if(${field.propertyType.equals("boolean")})#set($getprefix="is")#else#set($getprefix="get")#end

    public ${field.propertyType} ${getprefix}${field.capitalName}() {        return ${field.propertyName};
    }#if(${entityBuilderModel})
    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {#else
    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {#end
        this.${field.propertyName} = ${field.propertyName};#if(${entityBuilderModel})
        return this;#end
    }#end#end#if(${entityColumnConstant})#foreach($field in ${table.fields})
    public static final String ${field.name.toUpperCase()} = "${field.name}";#end#end#if(${activeRecord})
    @Override
    protected Serializable pkVal() {#if(${keyPropertyName})
        return this.${keyPropertyName};#else
        return this.id;#end
    }#end#if(!${entityLombokModel})
    @Override
    public String toString() {        return "${entity}{" +#foreach($field in ${table.fields})#if($!{velocityCount}==1)
        "${field.propertyName}=" + ${field.propertyName} +#else
        ", ${field.propertyName}=" + ${field.propertyName} +#end#end
        "}";
    }#end}

mapper.java.vm

package ${package.Mapper};import ${package.Entity}.${entity};import ${superMapperClassPackage};import ${cfg.commonPck}.BaseDto;import ${cfg.commonPck}.Query;import com.baomidou.mybatisplus.plugins.pagination.Pagination;import org.apache.ibatis.annotations.Param;import java.util.List;/**
 * <p>
 * $!{table.comment} Mapper 接口
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */#if(${kotlin})interface ${table.mapperName} : ${superMapperClass}<${entity}>
#elsepublic interface ${table.mapperName} extends ${superMapperClass}<${entity}> {

    List<${entity}> queryPageList(Pagination page,@Param("query") Query<BaseDto> query);

}
#end

mapper.xml.vm

package ${package.Service};

import ${package.Entity}.${entity};
import ${superServiceClassPackage};
import java.util.Map;
import ${cfg.commonPck}.PageInfo;
import ${cfg.commonPck}.BaseDto;

/**
 * <p>
 * $!{table.comment} 服务类
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */#if(${kotlin})interface ${table.serviceName} : ${superServiceClass}<${entity}>#elsepublic interface ${table.serviceName} extends ${superServiceClass}<${entity}> {

    /**
     * 分页查询
     * @param dto
     * @return
     */
    PageInfo<${entity}> queryPage(BaseDto<${entity}> dto);
}#end

service.java.vm

package ${package.Service};

import ${package.Entity}.${entity};
import ${superServiceClassPackage};
import java.util.Map;
import ${cfg.commonPck}.PageInfo;
import ${cfg.commonPck}.BaseDto;

/**
 * <p>
 * $!{table.comment} 服务类
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */#if(${kotlin})interface ${table.serviceName} : ${superServiceClass}<${entity}>#elsepublic interface ${table.serviceName} extends ${superServiceClass}<${entity}> {

    /**
     * 分页查询
     * @param dto
     * @return
     */
    PageInfo<${entity}> queryPage(BaseDto<${entity}> dto);
}#end

serviceImpl.java.vm

package ${package.ServiceImpl};import ${package.Entity}.${entity};import ${package.Mapper}.${table.mapperName};import ${package.Service}.${table.serviceName};import ${superServiceImplClassPackage};import java.util.List;import ${cfg.commonPck}.PageInfo;import ${cfg.commonPck}.BaseDto;import ${cfg.commonPck}.Query;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.springframework.stereotype.Service;/**
 * <p>
 * $!{table.comment} 服务实现类
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */@Service#if(${kotlin})open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {

    }
#else
    public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}>implements ${table.serviceName} {    private Logger log=LogManager.getLogger(this.getClass().getName());    /**
     * 分页查询
     * @param dto
     * @return
     */
    public PageInfo<${entity}>queryPage(BaseDto<${entity}> dto){

    Query<BaseDto>query=new Query<>(dto);
    List<${entity}>list=this.baseMapper.queryPageList(query.getPage(),query);    return new PageInfo<>(query.getPage(),list);
    }

    }
#end

最后编写一main运行工具类,运行main方法即可实现相关的类的构建。

public class MpGenerator {

	public static void main(String[] args) {		//生成代码
		MpGeneratorUtil.generateCode();
	}

}

其中配置文件中的有些配置需要修改为自己项目的配置,希望这段代码对有需要的朋友有帮助,有错误欢迎指正。

79f815e66571532398926cbb2bcf76d8.png

往期推荐

  1. 肝九千字长文 | MyBatis-Plus 码之重器 lambda 表达式使用指南,开发效率瞬间提升80%

  2. 用 MHA 做 MySQL 读写分离,频繁爆发线上生产事故后,泪奔分享 Druid 连接池参数优化实战

  3. 微服务架构下,解决数据库跨库查询的一些思路

  4. 一文读懂阿里大中台、小前台战略

作者简介猿芯,一枚简单的北漂程序员。喜欢用简单的文字记录工作与生活中的点点滴滴,愿与你一起分享程序员灵魂深处真正的内心独白。我的微信号:WooolaDunzung,公众号【猿芯输入 1024 ,有份面试惊喜送给你哦

< END >

【猿芯】

8a031433dd95d62709f7d1e13debff97.png

 微信扫描二维码,关注我的公众号。

分享不易,莫要干想,如果觉得有点用的话,动动你的发财之手,一键三连击:分享、点赞、在看,你们的鼓励是我分享优质文章的最强动力 ^_^

分享、点赞、在看,3连3连!000d3fccdf208ca141236a470dd66de7.gif


http://www.niftyadmin.cn/n/1240555.html

相关文章

php 和mysql实现抢购功能_php结合redis实现高并发下的抢购、秒杀功能 (转)

抢购、秒杀是如今很常见的一个应用场景&#xff0c;主要需要解决的问题有两个&#xff1a;1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少("超卖"问题)对于第一个问题&#xff0c;已经很容易想到用缓存来处理抢购&#xff0c;避免直接操作数据库&…

python的迭代器坑_Python中一些深不见底的“坑”

Python是一门清晰简洁的语言&#xff0c;如果你对一些细节不了解的话&#xff0c;就会掉入到那些深不见底的“坑”里&#xff0c;下面&#xff0c;我就来总结一些Python里常见的坑。列表创建和引用嵌套列表的创建使用*号来创建一个嵌套的list:li [[]] * 3print(li)# Out: [[],…

纵观jBPM从jBPM3到jBPM5以及Activiti

对jBPM来说&#xff0c;今年最大的事件莫过于jBPM的创建者Tom Baeyens离开JBoss了。Tom Baeyens离开的具体原因尚不清楚&#xff0c;但他的离开产生了两个结果&#xff1a;一是jBPM的下一个版本jBPM5完全放弃了jBPM4的基础代码&#xff0c;基于Drools Flow重头来过&#xff1b;…

java ClockRepairs_java 从零开始手写 redis(11)clock时钟淘汰算法详解及实现

前言前面我们实现了 FIFO/LRU/LFU 等常见的淘汰策略&#xff0c;不过在操作系统中&#xff0c;实际上使用的是时钟页面置换算法。LRU 的性能确实很好&#xff0c;不过比较消耗内存&#xff0c;而且实现比较麻烦。时钟页面置换算法就是一种近似 LRU 的算法实现&#xff0c;可以看…

Java使用JaxWsDynamicClientFactory和HttpURLConnection调取Webservice接口

点击上方“猿芯”&#xff0c;选择“设为星标”后台回复"1024"&#xff0c;有份惊喜送给面试的你方式1. 代理类工厂的方式,需要拿到对方的接口try {// 接口地址// 代理工厂JaxWsProxyFactoryBean jaxWsProxyFactoryBean new JaxWsProxyFactoryBean();// 设置代理地…

python isnumberic用法_Python 数据类型用法

1&#xff1a;整数类型(int)1&#xff1a;用途int:记录年龄,等级,岁月等2&#xff1a;定义方式>>> x 10>>> id(x)1489303616>>> type(x)2&#xff1a;浮点数类型(float)1&#xff1a;用途float:记录重量&#xff0c;工资等2&#xff1a;定义方式&g…

python数据库实例_python使用BerkeleyDB数据库实例

try:from bsddb import dbexcept ImportError:from bsddb3 import dbprint db.DB_VERSION_STRING#检测是否有bsddb包def irecords(curs):record curs.first()while record:yield recordrecord curs.next()adb db.DB()adb.open(db_filename,dbtype db.DB_HASH, flags db.DB…

老鸟必修代码精简技能:Lambda表达式

点击上方“猿芯”&#xff0c;选择“设为星标”后台回复"1024"&#xff0c;有份惊喜送给面试的你Lambda 是一个匿名函数&#xff0c;我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更…