JDK 1.8
spring-boot 2.4
lombok
druid 1.1.18
mybatis-plus 3.1.0
mybatis-plus-generator 3.1.0
velocity-engine-core 2.1
工程目录
1.创建项目
创建一个 springboot 的项目,或者直接复用自己已有的 maven 项目
File - New - Project - Spring Initializr (选jdk1.8和default)
创建完成后,等待下载对应的依赖。
2.pom文件依赖
因为我的是 oracle 数据库所以使用了 ojdbc 和 druid
mysql 可以直接使用 druid 和 mysql的驱动 jar
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ilyuc</groupId>
<artifactId>generatecode</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>GenerateCode</name>
<description>Generate Code project for DataBase</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.18</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
<scope>system</scope>
<systemPath>${basedir}/src/lib/ojdbc7-12.1.0.2.jar</systemPath>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.application.yml
如果直接使用测试类来实现,可以无视这部分
spring:
application:
name: generatecode
profiles:
active: dev
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@10.100.100.100:1529/abc
username: username
password: 123456
druid:
filter:
config:
enabled: true
connect-properties:
config.decrypt: true
# public key
config.decrypt.key: Uer-syglUj+lsd33==SDFsuqed.123sd
max-active: 500
min-idle: 10
initial-size: 10
validationQuery: SELECT 1 FROM DUAL
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# white list, blank is permitted all
allow:
url-pattern: /monitor/druid/*
devtools:
livereload:
enabled: true
server:
port: 8080
#mybatis
mybatis-plus:
mapper-locations: classpath:com/abc/*/mapper/*.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.abc.*.entity
global-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
id-type: 1
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: 2
#驼峰下划线转换
db-column-underline: true
#刷新mapper 调试神器
refresh-mapper: true
#数据库大写下划线转换
capital-mode: true
#序列接口实现类配置,不在推荐使用此方式进行配置,请使用自定义bean注入
#key-generator: com.baomidou.mybatisplus.incrementer.H2KeyGenerator
#逻辑删除配置(下面3个配置)
logic-delete-value: 0
logic-not-delete-value: 1
#自定义sql注入器,不在推荐使用此方式进行配置,请使用自定义bean注入
#sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
#自定义填充策略接口实现,不在推荐使用此方式进行配置,请使用自定义bean注入
#meta-object-handler: com.baomidou.springboot.MyMetaObjectHandler
#自定义SQL注入器
#sql-injector: com.baomidou.springboot.xxx
# SQL 解析缓存,开启后多租户 @SqlParser 注解生效
sql-parser-cache: true
configuration:
#配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId)
map-underscore-to-camel-case: true
cache-enabled: false
#配置JdbcTypeForNull, oracle数据库必须配置
jdbc-type-for-null: null
parameter-maps:
4.创建执行类
该类是从 yml 配置中获取的参数
也可以直接把数据源的参数写死
package com.ilyuc.generatecode.util;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @author ilyuc
* @version v 1.0.0
* @Description
* @date 2020/11/26 14:11
*/
@Service
public class GenerateCodeServiceImpl {
@Value("${spring.datasource.driver-class-name}")
private String driver;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
public void generate() {
System.out.println(driver);
System.out.println(url);
System.out.println(username);
System.out.println(password);
AutoGenerator mpg = new AutoGenerator();
//1. 全局配置
GlobalConfig config = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
config.setActiveRecord(true) // 是否支持AR模式
.setAuthor("ilyuc") // 作者
.setOutputDir(projectPath + "/src/main/java") // 生成路径
.setOpen(false)//生成后是否打开文件夹
.setFileOverride(true) // 文件覆盖
.setIdType(IdType.AUTO) // 主键策略
.setServiceName("%sService") // 自定义service名
// .setMapperName("%sMapper") //自定义mapper名
// .setXmlName("%sMapper") //自定义xml名
// .setServiceImplName("I%sServiceImpl") //自定义serviceImpl名
// .setControllerName("%sController") //自定义controller名
.setActiveRecord(true) // 不需要ActiveRecord特性的请改为false
.setBaseResultMap(true)//生成基本的resultMap
//.setSwagger2(true) //实体属性 Swagger2 注解
.setBaseColumnList(true);//生成基本的SQL片段
mpg.setGlobalConfig(config);
//2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
dsConfig.setDbType(DbType.ORACLE) // 设置数据库类型
.setDriverName(driver)
.setUrl(url)
.setUsername(username)
.setPassword(password);
mpg.setDataSource(dsConfig);
//3. 策略配置
StrategyConfig stConfig = new StrategyConfig();
stConfig.setCapitalMode(true) //全局大写命名
// .setDbColumnUnderline(true) // 指定表名 字段名是否使用下划线
.setNaming(NamingStrategy.underline_to_camel) // 数据库表映射到实体的命名策略
.setColumnNaming(NamingStrategy.underline_to_camel)
.setEntityLombokModel(false)//是否使用lombok注解方式
.setEntityTableFieldAnnotationEnable(false) //实体类上面生成表名注解TableName,成员变量上字段名注解TableField
.setInclude("USER_MODEL"); // 要生成文件的表,多个表就传数组
mpg.setStrategy(stConfig);
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("com.ilyuc.material") //父包名,路径为 com.ilyuc.material.controller
.setController("controller") //controller包名
.setService("service") //servcie包名
.setMapper("dao") //dao包名
.setEntity("entity") //实体类文件名
.setXml("mapper"); //mapper.xml
mpg.setPackageInfo(pkConfig);
//5. 自定义模板
TemplateConfig template = new TemplateConfig();
template.setController("templates/mycontroller.vm")
.setService("templates/myservice.vm")
.setServiceImpl("templates/myserviceImpl.vm")
.setMapper("templates/mymapper.vm")
.setXml("templates/myxml.vm")
.setEntity("templates/myentity.vm");
mpg.setTemplate(template);//或者注解掉使用默认模板
mpg.execute();
}
}
- 自定义模板可以先去掉,会加载 mybatis-plus-generator-3.1.0.jar
中默认的 templates 来生成,后续我们可以把里面的模板给复制出来,
做自定义修改
5.自定义模板
- mycontroller.vm
package ${package.Controller};
import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.util.List;
/**
* $!{table.comment} 前端控制器
* @author ${author}
* @since ${date}
*/
@RestController
@RequestMapping("/${table.entityPath}" )
public class ${table.controllerName} {
@Autowired
private ${table.serviceName} ${table.entityPath}Service;
/**
* 保存
*
* @param model
* @return
*/
@RequestMapping("/save")
public Object save(@RequestBody ${entity} model) {
${table.entityPath}Service.save(model);
return "success";
}
/**
* 修改
*
* @param model
* @return
*/
@PostMapping(value = "/update")
public ResponseEntity update(@RequestBody ${entity} model) {
${table.entityPath}Service.updateById(model);
return ResponseEntity.ok().build();
}
/**
* 查询详情
*
* @param id
* @return
*/
@RequestMapping("/getById")
public Object getById(Integer id) {
${entity} model = ${table.entityPath}Service.getById(id);
// todo 再包装一层
return model;
}
/**
* 删除
*
* @param id
* @return
*/
@DeleteMapping(value = "/{id}")
public ResponseEntity delete(@PathVariable String id) {
${table.entityPath}Service.removeById(id);
return ResponseEntity.ok().build();
}
/**
* 列表查询(非分页)
*
* @return
*/
@RequestMapping("/list")
public Object list() {
${entity} model = new ${entity}();
List<${entity}> list = ${table.entityPath}Service.list(model);
// todo 再包装一层
return list;
}
##/**
##* 列表查询(分页)
##*
##* @return
##*/
##@RequestMapping("/pageList")
##public Object pageList(Integer pageNum, Integer pageSize) {
##${entity} model = new ${entity}();
##IPage<User> page = ${table.entityPath}Service.pageList(model, pageNum, pageSize);
## // todo 再包装一层
## return page;
## }
}
- myservice.vm
package ${package.Service};
import ${package.Entity}.${entity};
import ${superServiceClassPackage};
import java.util.List;
import com.baomidou.mybatisplus.core.metadata.IPage;
/**
* <p>
* $!{table.comment} 服务类
* </p>
*
* @author ${author}
* @since ${date}
*/
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
/**
* 查询
*
* @param model
* @return
*/
List<${entity}> list(${entity} model);
/**
* 分页查询
*
* @param model
* @param pageNum 第几页
* @param pageSize 每页数量
* @return
*/
IPage<${entity}> pageList(${entity} model, Integer pageNum, Integer pageSize);
}
- myserviceImpl.vm
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
/**
* <p>
* $!{table.comment} 服务实现类
* </p>
*
* @author ${author}
* @since ${date}
*/
@Service
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {
@Override
public List< ${entity}> list(${entity} model) {
QueryWrapper< ${entity}> wrapper = new QueryWrapper();
return super.list(wrapper);
}
@Override
public IPage< ${entity}> pageList( ${entity} model, Integer pageNum, Integer pageSize) {
QueryWrapper< ${entity}> wrapper = new QueryWrapper(model);
return this.page(new Page<>(pageNum, pageSize), wrapper);
}
}
- mymapper.vm
package ${package.Mapper};
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
/**
* <p>
* $!{table.comment} Mapper 接口
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${kotlin})
interface ${table.mapperName} : ${superMapperClass}<${entity}>
#else
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
}
#end
- myxml.vm
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package.Mapper}.${table.mapperName}">
#if(${enableCache})
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
#end
#if(${baseResultMap})
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
#foreach($field in ${table.fields})
#if(${field.keyFlag})##生成主键排在第一位
<id column="${field.name}" property="${field.propertyName}" />
#end
#end
#foreach($field in ${table.commonFields})##生成公共字段
<result column="${field.name}" property="${field.propertyName}" />
#end
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
<result column="${field.name}" property="${field.propertyName}" />
#end
#end
</resultMap>
#end
#if(${baseColumnList})
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
#foreach($field in ${table.commonFields})
${field.name},
#end
${table.fieldNames}
</sql>
<select id="selectList" resultType="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM ${table.name}
</select>
#end
</mapper>
- myentity.vm
package ${package.Entity};
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end
#if(${swagger2})
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#end
#if(${entityLombokModel})
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
#end
/**
* <p>
* $!{table.comment}
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${entityLombokModel})
@Data
#if(${superEntityClass})
@EqualsAndHashCode(callSuper = true)
#else
@EqualsAndHashCode(callSuper = false)
#end
@Accessors(chain = true)
#end
#if(${table.convert})
@TableName("${table.name}")
#end
#if(${swagger2})
@ApiModel(value="${entity}对象", description="$!{table.comment}")
#end
#if(${superEntityClass})
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end {
#elseif(${activeRecord})
public class ${entity} extends Model<${entity}> {
#else
public class ${entity} implements Serializable {
#end
#if(${entitySerialVersionUID})
private static final long serialVersionUID=1L;
#end
## ---------- BEGIN 字段循环遍历 ----------
#foreach($field in ${table.fields})
#if(${field.keyFlag})
#set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
#if(${swagger2})
@ApiModelProperty(value = "${field.comment}")
#else
/**
* ${field.comment}
*/
#end
#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
## --foreach end---
#end
## --end of #if(!${entityLombokModel})--
#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 null;
#end
}
#end
#if(!${entityLombokModel})
@Override
public String toString() {
return "${entity}{" +
#foreach($field in ${table.fields})
#if($!{foreach.index}==0)
"${field.propertyName}=" + ${field.propertyName} +
#else
", ${field.propertyName}=" + ${field.propertyName} +
#end
#end
"}";
}
#end
}
(完)