一, 添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
二, 数据库连接配置
spring.r2dbc.username=root
spring.r2dbc.password=cl8q!a#jrkYgMBHu
spring.r2dbc.url=r2dbcs:mysql://172.16.1.187:2883/ob_test?userSSL=false&useUnicode=true&characterEncoding=UTF-8&sslMode=DISABLED&serverTimeZone=GMT%2B8
三, 编写模版文件
controller模板
package ${package.Controller};
import io.swagger.annotations.ApiResponse;
import com.shuinfo.ods_poc.vo.${entity}.${entity}SaveReq;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import io.swagger.v3.oas.annotations.Operation;
import com.fasterxml.jackson.annotation.JsonView;
import com.shuinfo.ods_poc.view.TestView;
import com.shuinfo.ods_poc.vo.R;
import ${package.Service}.${table.serviceName};
import com.shuinfo.ods_poc.vo.${entity}.${entity}SaveResp;
import reactor.core.publisher.Mono;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* ${table.comment!} 前端控制器
* @author ${author}
* @since ${date}
*/
@RestController
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
@Slf4j
public class ${table.controllerName} {
@Autowired
private ${table.serviceName} ${table.serviceName?uncap_first};
@PutMapping("/save")
@Operation(summary = "保存数据")
@JsonView(value = TestView.class)
@ApiResponse(code = 200, message = "返回数据", response = R.class)
public Mono<R<${entity}SaveResp>> save(@RequestBody ${entity}SaveReq req){
return ${table.serviceName?uncap_first}.save(req).map(R::successRespons);
}
@GetMapping("/delete")
@Operation(summary = "根据单号删除数据")
@JsonView(value = TestView.class)
@ApiResponse(code = 200, message = "返回数据", response = R.class)
public Mono<String> delete(@RequestParam("orderNo") String orderNo){
return ${table.serviceName?uncap_first}.delete(orderNo);
}
}
dao模版:
package ${package.Mapper};
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import ${package.Entity}.${entity};
public interface ${table.mapperName} extends R2dbcRepository<${entity}, Long> {
}
serviceImpl模版:
package ${package.Service};
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ${package.Mapper}.${table.mapperName};
import ${package.Entity}.${entity};
import com.shuinfo.ods_poc.vo.${entity}.${entity}SaveReq;
import com.shuinfo.ods_poc.vo.${entity}.${entity}SaveResp;
import reactor.core.publisher.Mono;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
/**
* <p>
* ${table.comment!} 服务实现类
* @author ${author}
* @since ${date}
*/
@Service
@Slf4j
public class ${table.serviceName}{
@Autowired
private ${table.mapperName} ${table.mapperName?uncap_first};
@Autowired
private R2dbcEntityTemplate r2dbcEntityTemplate;
public Mono<${entity}SaveResp> save(${entity}SaveReq req) {
${entity}SaveResp resp = new ${entity}SaveResp();
if(req == null || StringUtils.isEmpty(req.getOrderNo())){
return Mono.just(resp);
}
${entity} ${entity?uncap_first} = new ${entity}();
BeanUtils.copyProperties(req,${entity?uncap_first});
return ${table.mapperName?uncap_first}.save(${entity?uncap_first}).log().map(entity -> {
resp.set${entity}(entity);
return resp;
});
}
public Mono<String> delete(String orderNo) {
if(StringUtils.isEmpty(orderNo)){
return Mono.just("订单号不能为空!");
}
String sql = "delete from `${table.name}` where order_no = :orderNo";
return r2dbcEntityTemplate.getDatabaseClient().sql(sql).bind("orderNo",orderNo)
.then().thenReturn("删除成功!");
}
}
entity模版
package ${package.Entity};
import io.swagger.annotations.ApiModelProperty;
<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
<#if chainModel>
import lombok.experimental.Accessors;
</#if>
</#if>
/**
* <p>
* ${table.comment!}
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
<#if chainModel>
@Accessors(chain = true)
</#if>
</#if>
<#if table.convert>
@TableName("${schemaName}${table.name}")
</#if>
<#if swagger>
@ApiModel(value = "${entity}对象", description = "${table.comment!}")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#elseif entitySerialVersionUID>
public class ${entity} implements Serializable {
<#else>
public class ${entity} {
</#if>
<#if entitySerialVersionUID>
private static final long serialVersionUID = 1L;
</#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
<#if swagger>
@ApiModelProperty("${field.comment}")
<#else>
/**
* ${field.comment}
*/
</#if>
</#if>
<#if field.keyFlag>
<#-- 主键 -->
<#if field.keyIdentityFlag>
@TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
<#elseif field.convert>
@TableId("${field.annotationColumnName}")
</#if>
<#-- 普通字段 -->
<#elseif field.fill??>
<#-- ----- 存在字段填充设置 ----->
<#if field.convert>
@TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
<#else>
@TableField(fill = FieldFill.${field.fill})
</#if>
<#elseif field.convert>
@TableField("${field.annotationColumnName}")
</#if>
<#-- 乐观锁注解 -->
<#if field.versionField>
@Version
</#if>
<#-- 逻辑删除注解 -->
<#if field.logicDeleteField>
@TableLogic
</#if>
@ApiModelProperty(value = "${field.comment}")
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
<#if chainModel>
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
<#else>
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if chainModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
public Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#if !entityLombokModel>
@Override
public String toString() {
return "${entity}{" +
<#list table.fields as field>
<#if field_index==0>
"${field.propertyName}=" + ${field.propertyName} +
<#else>
", ${field.propertyName}=" + ${field.propertyName} +
</#if>
</#list>
"}";
}
</#if>
}
四, 编写入口生成主类
package org.flywaydb.core.internal.database.generate;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class R2dbcGenerate {
/**
* 数据源配置
*/
private static final DataSourceConfig.Builder DATA_SOURCE_CONFIG = new DataSourceConfig
.Builder("jdbc:mysql://172.16.1.187:2883/ob_test?userSSL=false&useUnicode=true" +
"&characterEncoding=UTF-8&sslMode=DISABLED&serverTimeZone=GMT%2B8",
"root", "cl8q!a#jrkYgMBHu");
private static GlobalConfig.Builder builder;
/**
* 执行 run
*/
public static void main(String[] args){
FastAutoGenerator.create(DATA_SOURCE_CONFIG)
// 全局配置
.globalConfig(builder -> builder
.author("zhihao").dateType(DateType.TIME_PACK)
.commentDate("yyyy-MM-dd")
// 输出路径
.outputDir("/Users/lizhihao/shuxin/wlc/starbuck-ods-webflux-poc/src/main/java")
)
// 包配置
.packageConfig(builder -> builder.parent("com.shuinfo.ods_poc.test")
// .packageConfig(builder -> builder.parent("com.shuinfo.ods_poc")
//自定义mapper名,同dao
.mapper("dao")
.other("vo")
// .pathInfo(Collections.singletonMap(OutputFile.other,
// "/Users/lizhihao/shuxin/wlc/starbuck-ods-webflux-poc/src/main/java/com/shuinfo/ods_poc/vo"))
)
// 策略配置 表名
.strategyConfig(builder -> builder.addInclude("main_order,order_customer,order_line," +
"order_line_discount,order_payment,order_price,order_service_type_config"))
/*
模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker
.templateEngine(new BeetlTemplateEngine())
*/
.templateEngine(new FreemarkerTemplateEngine())
.templateConfig(builder -> builder.disable(TemplateType.MAPPER)
.disable(TemplateType.SERVICEIMPL).disable(TemplateType.XML)
.disable(TemplateType.CONTROLLER)
.entity("/templates/entity")
.mapper("/templates/dao")
.service("/templates/serviceImpl")
.controller("/templates/controller")
)
//设置自定义的模块类及模版文件
.injectionConfig(builder ->
builder.beforeOutputFile((tableInfo, objectMap) -> {
//自定义入参对象
Map<String,String> map = new HashMap<>(10);
map.put(tableInfo.getEntityName()+"SaveReq.java", "/templates/req.ftl");
map.put(tableInfo.getEntityName()+"SaveResp.java", "/templates/resp.ftl");
builder.customFile(map);
System.out.println("tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size());
})
)
.execute();
}
}
五, 编写DataSourceConfig
/*
* Copyright (c) 2011-2021, baomidou (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.flywaydb.core.internal.database.generate;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.config.IConfigBuilder;
import com.baomidou.mybatisplus.generator.config.IDbQuery;
import com.baomidou.mybatisplus.generator.config.IKeyWordsHandler;
import com.baomidou.mybatisplus.generator.config.ITypeConvert;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.converts.TypeConverts;
import com.baomidou.mybatisplus.generator.config.querys.DbQueryDecorator;
import com.baomidou.mybatisplus.generator.config.querys.DbQueryRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Optional;
/**
* 数据库配置
*
* @author YangHu, hcl, hubin
* @since 2016/8/30
*/
public class DataSourceConfig {
protected final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);
private DataSourceConfig() {
}
/**
* 数据库信息查询
*/
private IDbQuery dbQuery;
/**
* schemaName
*/
private String schemaName;
/**
* 类型转换
*/
private ITypeConvert typeConvert;
/**
* 关键字处理器
*
* @since 3.3.2
*/
private IKeyWordsHandler keyWordsHandler;
/**
* 驱动连接的URL
*/
private String url;
/**
* 数据库连接用户名
*/
private String username;
/**
* 数据库连接密码
*/
private String password;
/**
* 数据源实例
*
* @since 3.5.0
*/
private DataSource dataSource;
/**
* 数据库连接
*
* @since 3.5.0
*/
private Connection connection;
/**
* 获取数据库查询
*/
public IDbQuery getDbQuery() {
if (null == dbQuery) {
DbType dbType = getDbType();
DbQueryRegistry dbQueryRegistry = new DbQueryRegistry();
// 默认 MYSQL
dbQuery = Optional.ofNullable(dbQueryRegistry.getDbQuery(dbType))
.orElseGet(() -> dbQueryRegistry.getDbQuery(DbType.MYSQL));
}
return dbQuery;
}
/**
* 判断数据库类型
*
* @return 类型枚举值
*/
public DbType getDbType() {
return this.getDbType(this.url.toLowerCase());
}
/**
* 判断数据库类型
*
* @param str url
* @return 类型枚举值,如果没找到,则返回 null
*/
private DbType getDbType(String str) {
if (str.contains(":mysql:") || str.contains(":cobar:")) {
return DbType.MYSQL;
} else if (str.contains(":oracle:")) {
return DbType.ORACLE;
} else if (str.contains(":postgresql:")) {
return DbType.POSTGRE_SQL;
} else if (str.contains(":sqlserver:")) {
return DbType.SQL_SERVER;
} else if (str.contains(":db2:")) {
return DbType.DB2;
} else if (str.contains(":mariadb:")) {
return DbType.MARIADB;
} else if (str.contains(":sqlite:")) {
return DbType.SQLITE;
} else if (str.contains(":h2:")) {
return DbType.H2;
} else if (str.contains(":kingbase:") || str.contains(":kingbase8:")) {
return DbType.KINGBASE_ES;
} else if (str.contains(":dm:")) {
return DbType.DM;
} else if (str.contains(":zenith:")) {
return DbType.GAUSS;
} else if (str.contains(":oscar:")) {
return DbType.OSCAR;
} else if (str.contains(":firebird:")) {
return DbType.FIREBIRD;
} else if (str.contains(":xugu:")) {
return DbType.XU_GU;
} else if (str.contains(":clickhouse:")) {
return DbType.CLICK_HOUSE;
} else if (str.contains(":sybase:")) {
return DbType.SYBASE;
} else {
return DbType.OTHER;
}
}
/**
* 获取数据库字段类型转换
*/
public ITypeConvert getTypeConvert() {
if (null == typeConvert) {
DbType dbType = getDbType();
// 默认 MYSQL
typeConvert = TypeConverts.getTypeConvert(dbType);
if (null == typeConvert) {
typeConvert = MySqlTypeConvert.INSTANCE;
}
}
return typeConvert;
}
/**
* 创建数据库连接对象
* 这方法建议只调用一次,毕竟只是代码生成,用一个连接就行。
*
* @return Connection
* @see DbQueryDecorator#getConnection()
*/
public Connection getConn() {
try {
if (connection != null && !connection.isClosed()) {
return connection;
} else {
synchronized (this) {
if (dataSource != null) {
connection = dataSource.getConnection();
} else {
this.connection = DriverManager.getConnection(url, username, password);
}
}
}
String schema = StringUtils.isNotBlank(schemaName) ? schemaName : getDefaultSchema();
if (StringUtils.isNotBlank(schema)) {
schemaName = schema;
try {
connection.setSchema(schemaName);
} catch (Throwable t) {
logger.error("There may be exceptions in the driver and version of the database, " + t.getMessage());
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return connection;
}
/**
* 获取数据库默认schema
*
* @return 默认schema
* @since 3.5.0
*/
protected String getDefaultSchema() {
DbType dbType = getDbType();
String schema = null;
if (DbType.POSTGRE_SQL == dbType) {
//pg 默认 schema=public
schema = "public";
} else if (DbType.KINGBASE_ES == dbType) {
//kingbase 默认 schema=PUBLIC
schema = "PUBLIC";
} else if (DbType.DB2 == dbType) {
//db2 默认 schema=current schema
schema = "current schema";
} else if (DbType.ORACLE == dbType) {
//oracle 默认 schema=username
schema = this.username.toUpperCase();
}
return schema;
}
public String getSchemaName() {
return schemaName;
}
public IKeyWordsHandler getKeyWordsHandler() {
return keyWordsHandler;
}
public String getUrl() {
return url;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
/**
* 数据库配置构建者
*
* @author nieqiurong 2020/10/10.
* @since 3.5.0
*/
public static class Builder implements IConfigBuilder<DataSourceConfig> {
private final DataSourceConfig dataSourceConfig;
private Builder() {
this.dataSourceConfig = new DataSourceConfig();
}
/**
* 构造初始化方法
*
* @param url 数据库连接地址
* @param username 数据库账号
* @param password 数据库密码
*/
public Builder(String url, String username, String password) {
this();
if (StringUtils.isBlank(url)) {
throw new RuntimeException("无法创建文件,请正确输入 url 配置信息!");
}
this.dataSourceConfig.url = url;
this.dataSourceConfig.username = username;
this.dataSourceConfig.password = password;
}
/**
* 构造初始化方法
*
* @param dataSource 外部数据源实例
*/
public Builder(DataSource dataSource) {
this();
this.dataSourceConfig.dataSource = dataSource;
try {
Connection conn = dataSource.getConnection();
this.dataSourceConfig.url = conn.getMetaData().getURL();
this.dataSourceConfig.schemaName = conn.getSchema();
this.dataSourceConfig.connection = conn;
this.dataSourceConfig.username = conn.getMetaData().getUserName();
} catch (SQLException ex) {
throw new RuntimeException("构建数据库配置对象失败!", ex);
}
}
/**
* 设置数据库查询实现
*
* @param dbQuery 数据库查询实现
* @return this
*/
public Builder dbQuery(IDbQuery dbQuery) {
this.dataSourceConfig.dbQuery = dbQuery;
return this;
}
/**
* 设置数据库schema
*
* @param schemaName 数据库schema
* @return this
*/
public Builder schema(String schemaName) {
this.dataSourceConfig.schemaName = schemaName;
return this;
}
/**
* 设置类型转换器
*
* @param typeConvert 类型转换器
* @return this
*/
public Builder typeConvert(ITypeConvert typeConvert) {
this.dataSourceConfig.typeConvert = typeConvert;
return this;
}
/**
* 设置数据库关键字处理器
*
* @param keyWordsHandler 关键字处理器
* @return this
*/
public Builder keyWordsHandler(IKeyWordsHandler keyWordsHandler) {
this.dataSourceConfig.keyWordsHandler = keyWordsHandler;
return this;
}
/**
* 构建数据库配置
*
* @return 数据库配置
*/
@Override
public DataSourceConfig build() {
return this.dataSourceConfig;
}
}
}