SpringBlade bug/优化 代码生成器

一、问题

1、SQL脚本

DROP TABLE IF EXISTS `pms_brand`;
CREATE TABLE pms_brand
(	   
	create_user          bigint comment '创建人',
	create_time          datetime comment '创建时间',
	update_user          bigint comment '上次修改人',
	update_time          datetime comment '上次修改时间',
	is_deleted           int comment '是否已删除',
	sort                 int comment '排序',
	tenant_id            varchar(12) comment '租户id',
	create_dept          bigint comment '创建部门',
	
	id                   bigint not null auto_increment comment '编号',
	name                 varchar(64) comment '名称',
	letter               varchar(64) comment '每个汉字的首字母',
	product_count        int comment '关联产品数量',
	primary key (id)
);

2、生成后的代码



3、这个我自己用MyBatis-Plus的代码生成器生成的



4、出错的地方在于数据库问题

原来是数据库备注乱码了,估计是本地以前执行SQL语句的时候忘选择编码了




二、需要注意的地方

1、脚本编码问题

MySQL数据库执行脚本的时候,要注意脚本编码的问题,不然很容易就乱码了


2、数据库版本问题

MySQL数据库版本 5.x和6.x的版本相差比较大,jdbc的配置需要注意,注意就是下面的两个参数

有两个参数需要注意:nullCatalogMeansCurrentallowPublicKeyRetrieval

原文:
https://blog.csdn.net/jiaoshaoping/article/details/80748065
https://blog.csdn.net/Yuriey/article/details/80423504

可参考默认数据库链接的配置

#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/blade?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&serverTimezone=GMT%2B8
#spring.datasource.username=root
#spring.datasource.password=root
#author=Blade

3、在线代码生成器的问题

在使用前需要配置一下数据源,不然就会使用本地的blade数据库,在数据源管理就可以配置。


4、代码生成器本地调试调试问题

需要特别注意一下数据库链接地址

如是在blade-core-develop这个项目运行,数据库的配置在这里'resources/templates/code.properties'

如果是在org.springblade这个项目运行,就需要在线配置一下数据源的地址

这里也有一个数据库配置文件,我把源码改过一下,就没有用到这里的这个文件




三、代码的一些调整

1、修改的类




2、BladeCodeGenerator

/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl.html
 * <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.springblade.develop.support;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.converts.OracleTypeConvert;
import com.baomidou.mybatisplus.generator.config.converts.PostgreSqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.develop.constant.DevelopConstant;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 代码生成器配置类
 *
 * @author Chill
 */

@Slf4j
public class BladeCodeGenerator {


	// configGlobalConfig 方法使用-----------------------
	/**
	 * 代码所在服务名
	 */
	private String serviceName = "blade-service";
	/**
	 * 租户字段
	 */
	private String tenantColumn = "tenant_id";
	/**
	 * 是否包含包装器
	 */
	private Boolean hasWrapper = Boolean.FALSE;
	/**
	 * 输出路径
	 */
	private String outputDir;
	/**
	 * 是否启用swagger
	 */
	private Boolean isSwagger2 = Boolean.TRUE;
	/**
	 * 作者
	 */
	private String author;


	// configDataSource 方法使用-----------------------
	/**
	 * 数据库驱动名
	 */
	private String driverName;
	/**
	 * 数据库链接地址
	 */
	private String url;
	/**
	 * 数据库用户名
	 */
	private String username;
	/**
	 * 数据库密码
	 */
	private String password;


	// configStrategyConfig 方法使用-----------------------
	/**
	 * 需要去掉的表前缀
	 */
	private String[] tablePrefix = {"blade_"};
	/**
	 * 需要生成的表名(两者只能取其一)
	 */
	private String[] includeTables = {};
	/**
	 * 需要排除的表名(两者只能取其一)
	 */
	private String[] excludeTables = {};
	/**
	 * 是否包含基础业务字段
	 */
	private Boolean hasSuperEntity = Boolean.FALSE;
	/**
	 * 基础业务字段
	 */
	private String[] superEntityColumns = {"create_time" , "create_user" , "create_dept" , "update_time" , "update_user" , "status" , "is_deleted"};


	// configPackageConfig 方法使用-----------------------
	/**
	 * 代码生成的包名
	 */
	private String packageName = "org.springblade.test";


	// configPackageConfig 方法使用-----------------------
	/**
	 * 代码模块名称
	 */
	private String codeName;
	/**
	 * 代码所在系统
	 */
	private String systemName = DevelopConstant.SWORD_NAME;
	/**
	 * 前端代码生成的地址
	 */
	private String packageWebDir;


	// getOutputDir 方法使用-----------------------
	/**
	 * 后端代码生成的地址
	 */
	private String packageDir;



	/**
	 * CodeGenerator这个类使用
	 * @param codeName 代码模块名称
	 * @param serviceName 代码所在服务名
	 * @param systemName 代码所在系统
	 * @param packageName 代码生成的包名
	 * @param packageWebDir 前端代码生成的地址
	 * @param tablePrefix 需要去掉的表前缀
	 * @param includeTables 需要生成的表名(两者只能取其一)
	 * @param excludeTables 需要排除的表名(两者只能取其一)
	 * @param hasSuperEntity 是否包含基础业务字段
	 * @param superEntityColumns 基础业务字段
	 */
	public BladeCodeGenerator(String codeName,String serviceName,String systemName,String packageName
		,String packageWebDir,String[] tablePrefix,String[] includeTables,String[] excludeTables
		,boolean hasSuperEntity,String[] superEntityColumns) {
		this.codeName=codeName;
		this.serviceName=serviceName;
		this.systemName=systemName;
		this.packageName=packageName;
		this.packageWebDir=packageWebDir;
		this.tablePrefix=tablePrefix;
		this.includeTables=includeTables;
		this.excludeTables=excludeTables;
		this.hasSuperEntity=hasSuperEntity;
		this.superEntityColumns=superEntityColumns;

		// 从配置文件获取数据库链接
		Properties props = getProperties();
		this.driverName = props.getProperty("spring.datasource.driver-class-name");
		this.url = props.getProperty("spring.datasource.url");
		this.username = props.getProperty("spring.datasource.username");
		this.password = props.getProperty("spring.datasource.password");
		this.author = props.getProperty("author");
	}

	/**
	 * CodeController类使用
	 * @param driverName 数据库驱动名
	 * @param url 数据库链接地址
	 * @param username 数据库用户名
	 * @param password 数据库密码
	 * @param systemName 代码所在系统
	 * @param serviceName 代码所在服务名
	 * @param packageName 代码生成的包名
	 * @param packageDir 后端代码生成的地址
	 * @param packageWebDir 前端代码生成的地址
	 * @param tablePrefix 需要去掉的表前缀
	 * @param includeTables 需要生成的表名(两者只能取其一)
	 * @param hasSuperEntity 需要排除的表名(两者只能取其一)
	 * @param hasWrapper 是否包含基础业务字段
	 */
	public BladeCodeGenerator(String driverName,String url,String username,String password
		,String systemName,String serviceName,String packageName,String packageDir,String packageWebDir
		,String[] tablePrefix,String[] includeTables,boolean hasSuperEntity,boolean hasWrapper){
		this.driverName=driverName;
		this.url=url;
		this.username=username;
		this.password=password;
		this.systemName=systemName;
		this.serviceName=serviceName;
		this.packageName=packageName;
		this.packageDir=packageDir;
		this.packageWebDir=packageWebDir;
		this.tablePrefix=tablePrefix;
		this.includeTables=includeTables;
		this.hasSuperEntity=hasSuperEntity;
		this.hasWrapper=hasWrapper;

		//其它值的初始化
		this.outputDir = getOutputDir();
	}



	/**
	 * 自定义生成文件配置
	 *
	 * @return
	 */
	private InjectionConfig configCustomerConfig() {
		String servicePackage = serviceName.split("-").length > 1 ? serviceName.split("-")[1] : serviceName;
		// 自定义配置
		Map<String, Object> map = new HashMap<>(16);
		InjectionConfig config = new InjectionConfig() {
			@Override
			public void initMap() {
				map.put("codeName" , codeName);
				map.put("serviceName" , serviceName);
				map.put("servicePackage" , servicePackage);
				map.put("servicePackageLowerCase" , servicePackage.toLowerCase());
				map.put("tenantColumn" , tenantColumn);
				map.put("hasWrapper" , hasWrapper);
				this.setMap(map);
			}
		};
		List<FileOutConfig> focList = new ArrayList<>();
		focList.add(new FileOutConfig("/templates/sql/menu.sql.vm") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				map.put("entityKey" , (tableInfo.getEntityName().toLowerCase()));
				map.put("menuId" , IdWorker.getId());
				map.put("addMenuId" , IdWorker.getId());
				map.put("editMenuId" , IdWorker.getId());
				map.put("removeMenuId" , IdWorker.getId());
				map.put("viewMenuId" , IdWorker.getId());
				return getOutputDir() + "/" + "/sql/" + tableInfo.getEntityName().toLowerCase() + ".menu.mysql";
			}
		});
		focList.add(new FileOutConfig("/templates/entityVO.java.vm") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return getOutputDir() + "/" + packageName.replace("." , "/") + "/" + "vo" + "/" + tableInfo.getEntityName() + "VO" + StringPool.DOT_JAVA;
			}
		});
		focList.add(new FileOutConfig("/templates/entityDTO.java.vm") {
			@Override
			public String outputFile(TableInfo tableInfo) {
				return getOutputDir() + "/" + packageName.replace("." , "/") + "/" + "dto" + "/" + tableInfo.getEntityName() + "DTO" + StringPool.DOT_JAVA;
			}
		});
		if (hasWrapper) {
			focList.add(new FileOutConfig("/templates/wrapper.java.vm") {
				@Override
				public String outputFile(TableInfo tableInfo) {
					return getOutputDir() + "/" + packageName.replace("." , "/") + "/" + "wrapper" + "/" + tableInfo.getEntityName() + "Wrapper" + StringPool.DOT_JAVA;
				}
			});
		}
		if (Func.isNotBlank(packageWebDir)) {
			if (Func.equals(systemName, DevelopConstant.SWORD_NAME)) {
				focList.add(new FileOutConfig("/templates/sword/action.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/actions" + "/" + tableInfo.getEntityName().toLowerCase() + ".js";
					}
				});
				focList.add(new FileOutConfig("/templates/sword/model.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/models" + "/" + tableInfo.getEntityName().toLowerCase() + ".js";
					}
				});
				focList.add(new FileOutConfig("/templates/sword/service.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/services" + "/" + tableInfo.getEntityName().toLowerCase() + ".js";
					}
				});
				focList.add(new FileOutConfig("/templates/sword/list.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/pages" + "/" + StringUtil.upperFirst(servicePackage) + "/" + tableInfo.getEntityName() + "/" + tableInfo.getEntityName() + ".js";
					}
				});
				focList.add(new FileOutConfig("/templates/sword/add.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/pages" + "/" + StringUtil.upperFirst(servicePackage) + "/" + tableInfo.getEntityName() + "/" + tableInfo.getEntityName() + "Add.js";
					}
				});
				focList.add(new FileOutConfig("/templates/sword/edit.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/pages" + "/" + StringUtil.upperFirst(servicePackage) + "/" + tableInfo.getEntityName() + "/" + tableInfo.getEntityName() + "Edit.js";
					}
				});
				focList.add(new FileOutConfig("/templates/sword/view.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/pages" + "/" + StringUtil.upperFirst(servicePackage) + "/" + tableInfo.getEntityName() + "/" + tableInfo.getEntityName() + "View.js";
					}
				});
			} else if (Func.equals(systemName, DevelopConstant.SABER_NAME)) {
				focList.add(new FileOutConfig("/templates/saber/api.js.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/api" + "/" + servicePackage.toLowerCase() + "/" + tableInfo.getEntityName().toLowerCase() + ".js";
					}
				});
				focList.add(new FileOutConfig("/templates/saber/crud.vue.vm") {
					@Override
					public String outputFile(TableInfo tableInfo) {
						return getOutputWebDir() + "/views" + "/" + servicePackage.toLowerCase() + "/" + tableInfo.getEntityName().toLowerCase() + ".vue";
					}
				});
			}
		}
		config.setFileOutConfigList(focList);
		return config;
	}

	/**
	 * 全局配置
	 *
	 * @return
	 */
	private GlobalConfig configGlobalConfig() {
		GlobalConfig config = new GlobalConfig();
		config.setOutputDir(this.outputDir);
		config.setAuthor(this.author);
		config.setFileOverride(true);
		config.setOpen(false);
		config.setActiveRecord(false);
		config.setEnableCache(false);
		config.setBaseResultMap(true);
		config.setBaseColumnList(true);
		config.setMapperName("%sMapper");
		config.setXmlName("%sMapper");
		config.setServiceName("I%sService");
		config.setServiceImplName("%sServiceImpl");
		config.setControllerName("%sController");
		config.setSwagger2(isSwagger2);
		return config;
	}

	/**
	 * 数据源配置
	 *
	 * @return
	 */
	private DataSourceConfig configDataSource() {
		DataSourceConfig config = new DataSourceConfig();

		if (StringUtil.containsAny(this.driverName, DbType.MYSQL.getDb())) {
			config.setDbType(DbType.MYSQL);
			config.setTypeConvert(new MySqlTypeConvert());
		} else if (StringUtil.containsAny(this.driverName, DbType.POSTGRE_SQL.getDb())) {
			config.setDbType(DbType.POSTGRE_SQL);
			config.setTypeConvert(new PostgreSqlTypeConvert());
		} else {
			config.setDbType(DbType.ORACLE);
			config.setTypeConvert(new OracleTypeConvert());
		}
		config.setDriverName(this.driverName);
		config.setUrl(this.url);
		config.setUsername(this.username);
		config.setPassword(this.password);
		return config;
	}

	/**
	 * 策略配置
	 *
	 * @return
	 */
	private StrategyConfig configStrategyConfig() {
		// 策略配置
		StrategyConfig config = new StrategyConfig();
		// config.setCapitalMode(true);// 全局大写命名
		// config.setDbColumnUnderline(true);//全局下划线命名
		config.setNaming(NamingStrategy.underline_to_camel);
		config.setColumnNaming(NamingStrategy.underline_to_camel);
		config.setTablePrefix(tablePrefix);
		if (includeTables.length > 0) {
			config.setInclude(includeTables);
		}
		if (excludeTables.length > 0) {
			config.setExclude(excludeTables);
		}
		if (hasSuperEntity) {
			config.setSuperEntityClass("org.springblade.core.mp.base.BaseEntity");
			config.setSuperEntityColumns(superEntityColumns);
			config.setSuperServiceClass("org.springblade.core.mp.base.BaseService");
			config.setSuperServiceImplClass("org.springblade.core.mp.base.BaseServiceImpl");
		} else {
			config.setSuperServiceClass("com.baomidou.mybatisplus.extension.service.IService");
			config.setSuperServiceImplClass("com.baomidou.mybatisplus.extension.service.impl.ServiceImpl");
		}
		// 自定义 controller 父类
		config.setSuperControllerClass("org.springblade.core.boot.ctrl.BladeController");
		config.setEntityBuilderModel(false);
		config.setEntityLombokModel(true);
		config.setControllerMappingHyphenStyle(true);

		return config;
	}

	/**
	 * 包名策略配置
	 *
	 * @return
	 */
	private PackageConfig configPackageConfig() {
		// 包配置
		PackageConfig config = new PackageConfig();
		// 控制台扫描
		config.setModuleName(null);
		config.setParent(packageName);
		config.setController("controller");
		config.setEntity("entity");
		config.setXml("mapper");
		return config;
	}



	/**
	 * 获取配置文件
	 *
	 * @return 配置Props
	 */
	private Properties getProperties() {
		// 读取配置文件
		Resource resource = new ClassPathResource("/templates/code.properties");
		Properties props = new Properties();
		try {
			props = PropertiesLoaderUtils.loadProperties(resource);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return props;
	}

	/**
	 * 生成到项目中
	 *
	 * @return outputDir
	 */
	public String getOutputDir() {
		return (Func.isBlank(packageDir) ? System.getProperty("user.dir") + "/blade-ops/blade-develop" : packageDir) + "/src/main/java";
	}

	/**
	 * 生成到Web项目中
	 *
	 * @return outputDir
	 */
	public String getOutputWebDir() {
		return (Func.isBlank(packageWebDir) ? System.getProperty("user.dir") : packageWebDir) + "/src";
	}

	/**
	 * 页面生成的文件名
	 */
	private String getGeneratorViewPath(String viewOutputDir, TableInfo tableInfo, String suffixPath) {
		String name = StringUtils.firstToLowerCase(tableInfo.getEntityName());
		String path = viewOutputDir + "/" + name + "/" + name + suffixPath;
		File viewDir = new File(path).getParentFile();
		if (!viewDir.exists()) {
			viewDir.mkdirs();
		}
		return path;
	}



	public void run() {
		AutoGenerator mpg = new AutoGenerator();
		mpg.setGlobalConfig(configGlobalConfig());
		mpg.setDataSource(configDataSource());
		mpg.setStrategy(configStrategyConfig());
		mpg.setPackageInfo(configPackageConfig());
		mpg.setCfg(configCustomerConfig());
		mpg.execute();
	}

}

3、CodeGenerator

public static void run() {
	BladeCodeGenerator generator = new BladeCodeGenerator(
		CODE_NAME,SERVICE_NAME,SYSTEM_NAME,PACKAGE_NAME
		,PACKAGE_WEB_DIR,TABLE_PREFIX,INCLUDE_TABLES
		,EXCLUDE_TABLES,HAS_SUPER_ENTITY,SUPER_ENTITY_COLUMNS
	);
	generator.run();
}

4、CodeController

/**
 * 代码生成
 */
@PostMapping("/gen-code")
@ApiOperationSupport(order = 6)
@ApiOperation(value = "代码生成" , notes = "传入ids")
public R genCode(@ApiParam(value = "主键集合" , required = true) @RequestParam String ids, @RequestParam(defaultValue = "sword") String system) {
	Collection<Code> codes = codeService.listByIds(Func.toLongList(ids));
	codes.forEach(code -> {

		String driverName = "";
		String url = "";
		String username = "";
		String password = "";
		String systemName = "";
		String serviceName = "";
		String packageName = "";
		String packageDir = "";
		String packageWebDir = "";
		String[] tablePrefix = null;
		String[] includeTables = null;
		boolean hasSuperEntity = false;
		boolean hasWrapper = false;

		// 设置数据源
		Datasource datasource = datasourceService.getById(code.getDatasourceId());
		driverName = datasource.getDriverClass();
		url = datasource.getUrl();
		username = datasource.getUsername();
		password = datasource.getPassword();

		// 设置基础配置
		systemName = system;
		serviceName = code.getServiceName();
		packageName = code.getPackageName();
		packageDir = code.getApiPath();
		packageWebDir = code.getWebPath();
		tablePrefix = Func.toStrArray(code.getTablePrefix());
		includeTables = Func.toStrArray(code.getTableName());
		hasSuperEntity = code.getBaseMode() == 2;
		hasWrapper = code.getWrapMode() == 2;

		//构造函数初始化
		BladeCodeGenerator generator = new BladeCodeGenerator(driverName, url, username, password
			, systemName, serviceName, packageName, packageDir, packageWebDir
			, tablePrefix, includeTables, hasSuperEntity, hasWrapper
		);

		generator.run();
	});
	return R.success("代码生成成功");
}

posted @ 2020-08-10 16:21  古兴越  阅读(2004)  评论(0编辑  收藏  举报