这次的主要灵感来源于EasyCode这个插件,可以通过Idea的数据库插件生成出实体类,非常方便,这里放一下官方的介绍图
可以看到插件为了通用性,牺牲了一些易用性。我们日常在公司里开发的项目的目录、代码风格大多是比较固定的,如果可以定制化,把很多配置写死的话,岂不美哉!
获取数据库表信息
首先要解决的问题就是如何获取到数据库表的信息
public static DbTable getDbTable(AnActionEvent anActionEvent) {
return (DbTable) anActionEvent.getData(LangDataKeys.PSI_ELEMENT);
}
同样也可以根据这个类型,判断action是否显示
@Override
public void update(@NotNull AnActionEvent anActionEvent) {
PsiElement psiElement = anActionEvent.getData(LangDataKeys.PSI_ELEMENT);
//通过这个方式控制插件是否显示和生效
anActionEvent.getPresentation().setEnabledAndVisible(psiElement instanceof DbTable);
}
在获取到表信息之后,通过下图的方式获取到列的属性
public static List<DasColumn> getDasColumnList(DbTable dbTable) {
return new ArrayList<>(DasUtil.getColumns(dbTable).toList());
}
DasColumn类里面可以获取到表的属性信息,比如通过getName()方法可以获取到属性名、getComment()可以获取到注释等
Freemarker模版
生成文件的模版采用Freemarker,此时需要一个配置类
public class FreemarkerMybatisConfiguration extends Configuration {
//入参是resource下的路径
public FreemarkerMybatisConfiguration(String basePackagePath) {
super(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
setDefaultEncoding("UTF-8");
setClassForTemplateLoading(getClass(), basePackagePath);
}
public Template getTemplate(String ftl) throws IOException {
return this.getTemplate(ftl, "UTF-8");
}
}
这边放一下我自己用的模版,其实大概就是循环数据库字段,生成java类,可以自行补充上包名,注释之类的信息
package ${packageInfo};
import lombok.Data;
import java.util.Date;
/**
* ${classInfo.comment}
*/
@Data
public class ${classInfo.name} {
<#list fieldInfoList as value>
/**
* ${value.comment}
*/
private ${value.type} ${value.name};
</#list>
}
生成文件
为了方便阅读,略去了一些try catch
大致思路如下
- 初始化模版并通过模版生成类的信息
- 写文件
- 格式化(生成的类,IDEA是有现成的工具来格式化的,所以其实我们也不用太在意模版的格式信息)
/**
* templateName: 模版名称(模版路径位置)
* param: 模版中定义的参数
* path: 文件生成的地址
* fileName: 最后生成的文件名称
*/
public static boolean writeByFreemarker(Project project, String templateName, Object param, String path, String fileName) {
//初始化并获取模版
FreemarkerMybatisConfiguration freemarkerMybatisConfiguration = new FreemarkerMybatisConfiguration("/template/mybatis");
Template template = freemarkerMybatisConfiguration.getTemplate(templateName);
//生成根据模版生成java类
StringWriter stringWriter = new StringWriter();
template.process(param, stringWriter);
boolean mkdirs = new File(path).mkdirs();
//写文件
VirtualFile virtualFile = Objects.requireNonNull(LocalFileSystem.getInstance().refreshAndFindFileByPath(path)).createChildData(project, fileName);
virtualFile.setBinaryContent(stringWriter.toString().getBytes(StandardCharsets.UTF_8));
PsiFile file = PsiManager.getInstance(project).findFile(virtualFile);
//通过这个方式可以直接格式化代码,所以模版里可以不用太在意格式信息
ReformatCodeProcessor reformatCodeProcessor = new ReformatCodeProcessor(project, file, null, false);
reformatCodeProcessor.run();
//理论上应该会整理导入包的,但是不知道为啥没成功。。。
JavaCodeStyleManager.getInstance(project).optimizeImports(Objects.requireNonNull(file));
return true;
}
生成文件的位置
设置文件生成到哪个目录,每个项目都不太一样,还是需要选择一下,IDEA提供了一个包选择器,用起来也非常简单
PackageChooserDialog packageChooserDialog = new PackageChooserDialog("Package Chooser", event.getProject());
packageChooserDialog.show();
PsiPackage selectedPackage = packageChooserDialog.getSelectedPackage();
selectedPackage就是我们最后选择的包
获取到PsiPackage之后,可以通过这种方式获取到包的绝对路径(不同模块可能会有同名的包,所以是个数组)
selectedPackage.getDirectories()[0].getVirtualFile().getPresentableUrl()
完成!
到这里其实关键的问题就都解决掉了,总步骤大概分为这几点
- 通过数据库插件获取到数据库表信息
- 将收集到的数据库信息转化为我们自己定义的模版中的属性
- 初始化模版,并在指定路径下生成文件
关键的代码在文中都已经提到啦,如果想看完整的代码的话可以下载源码
附一张最终效果图
(不知道为啥IDEA报了个错,哈哈哈哈)
本文的内容到这里就结束了,如果觉得有用的话,记得点个赞呀!