最近有在学习使用mybatis plus,了解到使用mp代码生成器可以方便快捷的生成代码,为了适用于自己开发需要,自定义了一个mp的代码生成器,增加了几个小功能:
1.增加了Vo类的生成,其实思路很简单,利用生成的entity实体类,复制一份,替换掉其中的几个关键字就可以了。
2.可以根据表名,根据参数判断是否去掉前缀,然后根据剩余部分自动生成包名,在批量生成时更好的区分每个表的数据。
代码如下:
public class CodeGeneratorPlus {
/**
* 数据库类型
*/
private static final DbType DATA_SOURCE_TYPE = DbType.MYSQL;
/**
* 数据库驱动
*/
private static final String DATA_SOURCE_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
/**
* 数据库连接
*/
private static final String DATA_SOURCE_URL = "jdbc:mysql://127.0.0.1:3306/localmysql?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";
/**
* 数据库用户名
*/
private static final String DATA_SOURCE_USER_NAME = "root";
/**
* 数据库连接密码
*/
private static final String DATA_SOURCE_PASSWORD = "root";
/**
* 数据库默认表空间名称
*/
private static final String DATA_SOURCE_SCHEMA_NAME = "";
/**
* 生成的代码默认输出文件目录
*/
private static final String DEFAULT_OUT_PUT_DIR = System.getProperty("user.dir") + "/src/main/java";
/**
* 默认包名称
*/
private static final String DEFAULT_PARENT_PACK = "cn.com.mtd";
/**
* 默认父级实体类全限定类名
*/
private static final String BASE_ENTITY_CLASS_NAME = "cn.com.mtd.entity.BaseEntity";
/**
* 公共父类实体类中含有的字段
*/
private static final String[] SUPPER_ENTITY_CONTAINS_FIELD = { "ID", "CREATE_BY", "UPDATE_BY", "CREATE_DATE","UPDATE_DATE", "DELETE_FLAG", "JI_GOU_ID" };
public static void main(String[] args) {
// 数据库表名称
String[] tableNames = { "REG_TI_JIAN_HAO_XU_HAO" };
// 1.得到全局配置参数
GlobalConfig config = getGlobalConfig();
// 2.得到数据源配置参数
DataSourceConfig dsConfig = getDataSourceConfig();
// 3.得到策略配置参数
StrategyConfig stConfig = null;
// 4. 包名策略配置
PackageConfig pkConfig = null;
boolean isTablePrefix = true;
for (int i = 0; i < tableNames.length; i++) {
// 5. 整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config).setDataSource(dsConfig);
String tableName = tableNames[i];
stConfig = getStrategyConfig(true, isTablePrefix, tableName);
ag.setStrategy(stConfig);
pkConfig = getPackageConfig(isTablePrefix, tableName);
ag.setPackageInfo(pkConfig);
// 6. 执行
ag.execute();
}
// 生成Vo对象
produceViewObject(isTablePrefix, tableNames);
System.out.println("代码生成完成!");
}
/**
* 根据表名生成VO对象,用于mybatis-plus代码生成以后再生成
*
* @param isTablePrefix
* @param tableNames
*/
private static void produceViewObject(boolean isTablePrefix, String... tableNames) {
for (int i = 0; i < tableNames.length; i++) {
String tableName = tableNames[i];
tableName = isTablePrefix ? tableName.substring(tableName.indexOf("_") + 1) : tableName;
String suPkStr = StringUtils.remove(tableName, "_").toLowerCase();
String outPutDir = DEFAULT_OUT_PUT_DIR + "/" + (DEFAULT_PARENT_PACK.replace(".", "/")) + "/vo/" + suPkStr
+ "/";
String baseFileName = StringUtil.underline2Camel(tableName, false);
try {
File outFile = new File(outPutDir);
if (!outFile.exists()) {
outFile.mkdirs();
}
File voFile = new File(outFile, baseFileName + "Vo.java");
if (!voFile.exists()) {
voFile.createNewFile();
}
BufferedReader reader = new BufferedReader(
new FileReader(DEFAULT_OUT_PUT_DIR + "/" + (DEFAULT_PARENT_PACK.replace(".", "/")) + "/entity/"
+ suPkStr + "/" + baseFileName + "Entity.java"));
FileWriter fw = new FileWriter(voFile);
String line = null;
while ((line = reader.readLine()) != null) {
// 将实体类中的entity变为Vo
line = line.replace("entity", "vo").replace("Entity", "Vo");
// 去掉mybatis-plus注解
if (line.contains("TableName") || line.contains("TableField") || line.contains("Accessors")) {
continue;
}
line += "
";
fw.write(line);
}
fw.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static PackageConfig getPackageConfig(boolean isTablePrefix, String tableName) {
// 包名策略配置
PackageConfig pkConfig = new PackageConfig();
tableName = isTablePrefix ? tableName.substring(tableName.indexOf("_") + 1) : tableName;
String suPkStr = StringUtils.remove(tableName, "_").toLowerCase();
pkConfig.setParent(DEFAULT_PARENT_PACK) // 父包
.setMapper("mapper." + suPkStr)// mapper文件的包名
.setService("service." + suPkStr)// servcie文件的包名
.setServiceImpl("service.impl." + suPkStr) // serviceimpl文件的包名
.setController("controller." + suPkStr)// controller文件的包名
.setEntity("entity." + suPkStr) // entity文件的包名
.setXml("mapper.mapping." + suPkStr); // mapper.xml文件存放的位置
return pkConfig;
}
/**
* 获取策略配置
*
* @param isExtendsSuper 是否基础默认父类
* @param isTablePrefix 表是否有需要取消的前缀
* @param tableNames 表名
* @return
*/
private static StrategyConfig getStrategyConfig(boolean isExtendsSuper, boolean isTablePrefix,
String... tableNames) {
// 3. 策略配置globalConfiguration中
if (tableNames == null || tableNames.length == 0) {
throw new RuntimeException("请不要传入空的表名参数!");
}
StrategyConfig stConfig = new StrategyConfig();
if (isTablePrefix) {
Set<String> prefixSet = new HashSet<>();
for (int i = 0; i < tableNames.length; i++) {
int index = tableNames[0].indexOf("_");
if (index != -1) {
prefixSet.add(tableNames[0].substring(0, index));
}
}
stConfig.setTablePrefix(prefixSet.toArray(new String[prefixSet.size()]));
}
if (isExtendsSuper) {
stConfig.setSuperEntityClass(BASE_ENTITY_CLASS_NAME) // 实体类继承的公共父类
.setSuperEntityColumns(SUPPER_ENTITY_CONTAINS_FIELD);// 父类中的字段 ,子类继承了父类会忽略这些字段
}
stConfig.setCapitalMode(true) // 全局大写命名
.setRestControllerStyle(false) // 生成 @RestController 控制器
// .setDbColumnUnderline(true)
.setEntityTableFieldAnnotationEnable(true) // 在实体类的字段上面添加注解映射数据的字段名称
// 数据库表映射到实体的命名策略
.setNaming(NamingStrategy.underline_to_camel) // 将数据库中有下划线分割的字段在实体类中转为驼峰命名法
.setColumnNaming(NamingStrategy.underline_to_camel).setEntityLombokModel(true)// 使用lombok注解模式
.setInclude(tableNames);
return stConfig;
}
private static DataSourceConfig getDataSourceConfig() {
// 2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
dsConfig.setDbType(DATA_SOURCE_TYPE) // 设置数据库类型
.setDriverName(DATA_SOURCE_DRIVER_CLASS_NAME) // 数据库驱动名称
.setUrl(DATA_SOURCE_URL)// 数据库连接url
.setUsername(DATA_SOURCE_USER_NAME) // 数据库用户
.setPassword(DATA_SOURCE_PASSWORD); // 数据库密码
if (StringUtils.isNotBlank(DATA_SOURCE_SCHEMA_NAME)) {
dsConfig.setSchemaName(DATA_SOURCE_SCHEMA_NAME);// 数据库表空间名称
}
return dsConfig;
}
private static GlobalConfig getGlobalConfig() {
// 1. 全局配置
GlobalConfig config = new GlobalConfig();
config.setActiveRecord(false) // 是否使用AR模式
.setAuthor("jinghx") // 类作者名称
.setOutputDir(DEFAULT_OUT_PUT_DIR) // 代码文件生成路径
.setFileOverride(true) // 文件是否覆盖
// .setIdType(IdType.NONE) // 主键策略
.setServiceName("%sService") // 设置生成的service接口的名字的首字母是否为I
.setServiceImplName("%sServiceImpl") // 设置Service实现类名称格式
.setMapperName("%sMapper") // 设置Mapper类的名称格式
.setControllerName("%sController") // 设置Controller类的名称格式
.setEntityName("%sEntity") // 设置Entity类的名称格式
.setOpen(false) // 生成文件后是否打开文件
.setBaseResultMap(true)// 在mapper.xml文件中生成基本的resultMap
.setBaseColumnList(true);// 在mapper.xml文件中生成基本的SQL片段
return config;
}
}
由下划线组成的字符串去掉下划线转小写,工具类:
/**
* 下划线转驼峰法(默认小驼峰)
*
* @param line 源字符串
* @param smallCamel 大小驼峰,是否为小驼峰(驼峰,第一个字符是大写还是小写)
* @return 转换后的字符串
*/
public static String underline2Camel(String line, boolean... smallCamel) {
if (StringUtils.isBlank(line)) {
return "";
}
StringBuffer sb = new StringBuffer();
Pattern pattern = Pattern.compile("([A-Za-z\d]+)(_)?");
Matcher matcher = pattern.matcher(line);
// 匹配正则表达式
while (matcher.find()) {
String word = matcher.group();
// 当是true 或则是空的情况
if ((smallCamel.length == 0 || smallCamel[0]) && matcher.start() == 0) {
sb.append(Character.toLowerCase(word.charAt(0)));
} else {
sb.append(Character.toUpperCase(word.charAt(0)));
}
int index = word.lastIndexOf('_');
if (index > 0) {
sb.append(word.substring(1, index).toLowerCase());
} else {
sb.append(word.substring(1).toLowerCase());
}
}
return sb.toString();
}