之前一直在Eclipse中使用MBG,JAVA文件entity和Mapper都是可以合并的,换了IDEA发现竟然不能正常合并,刚开始以为是配置的问题,查找了半天,发现原来MBG官方就是不支持合并JAVA文件的
如果想支持JAVA文件合并,那么需要自己实现,官方文档有类似说明(原来Eclipse插件就是额外实现的JAVA文件合并)
参考了网上不少资料,整理了一下符合自己习惯的解决方案
实现思路
在MBG的org.mybatis.generator.api.MyBatisGenerator构造方法中,是支持传入自定义的ShellCallback的,而org.mybatis.generator.internal.DefaultShellCallback中对于合并JAVA文件直接抛出了异常,未进行实现
public MyBatisGenerator(Configuration configuration, ShellCallback shellCallback, List<String> warnings) throws InvalidConfigurationException {
if (configuration == null) {
throw new IllegalArgumentException(Messages.getString("RuntimeError.2"));
} else {
this.configuration = configuration;
if (shellCallback == null) {
this.shellCallback = new DefaultShellCallback(false);
} else {
this.shellCallback = shellCallback;
}
if (warnings == null) {
this.warnings = new ArrayList();
} else {
this.warnings = warnings;
}
this.generatedJavaFiles = new ArrayList();
this.generatedXmlFiles = new ArrayList();
this.projects = new HashSet();
this.configuration.validate();
}
}
public String mergeJavaFile(String newFileSource, File existingFile, String[] javadocTags, String fileEncoding) throws ShellException {
throw new UnsupportedOperationException();
}
那么思路就是实现自定义的ShellCallback,实现mergeJavaFile方法
自定义Generator项目
新建Maven项目,增加MBG和javaparser依赖
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>3.2.10</version>
</dependency>
新建MyShellCallback并继承MBG的ShellCallback
public class MyShellCallback implements ShellCallback
重写mergeJavaFile方法(代码直接在网上找的现成的例子,感谢参考代码)
@Override
public String mergeJavaFile(
String newFileSource, File existingFile, String[] javadocTags,
String fileEncoding) throws ShellException {
CompilationUnit newCompilationUnit = JavaParser.parse(newFileSource);
CompilationUnit existingCompilationUnit = null;
try {
existingCompilationUnit = JavaParser.parse(existingFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/**
* 1. 合并import
*/
Set importSet = new HashSet<ImportDeclaration>();
importSet.addAll(newCompilationUnit.getImports());
importSet.addAll(existingCompilationUnit.getImports());
NodeList<ImportDeclaration> newImports = new NodeList<>();
newImports.addAll(importSet);
newCompilationUnit.setImports(newImports);
/**
* todo: 一个文件里面有多个类的情况没有考虑
* 2. 合并成员变量和成员方法
*/
TypeDeclaration<?> oldType = existingCompilationUnit.getType(0);
TypeDeclaration<?> newType = newCompilationUnit.getType(0);
NodeList members = oldType.getMembers();
// 遍历所有tag
for (String oldTag: javadocTags){
// 遍历所有的字段
// 删除所有带有特殊标记的字段
members.removeIf(member -> ((BodyDeclaration) member).getComment().toString().contains(oldTag));
}
// 添加所有没有特殊标记的成员到 新文件
newType.getMembers().addAll(members);
/**
* 3. 合并类的注解
*/
Set<AnnotationExpr> anSet = new HashSet<>();
anSet.addAll(oldType.getAnnotations());
anSet.addAll(newType.getAnnotations());
NodeList<AnnotationExpr> newAn = new NodeList<>();
newAn.addAll(anSet);
newType.setAnnotations(newAn);
return newCompilationUnit.toString();
}
由于自定义ShellCallback不能通过XML配置的方式使用,所以只能使用JAVA的方式调用MBG,官方文档有示例
由于会有不同项目使用自定义的generator,不想把执行代码挨个项目拷,所以把MBG执行JAVA类一起放到MyShellCallback的项目中
public class MybatisGenerator {
public static void main(String[] args) {
try {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("mybatis-generator.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
MyShellCallback callback = new MyShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
将新建的项目通过maven install到本地仓库中
业务项目使用自定义Generator
在业务项目中,通过引入新建的依赖项目,并在pom中配置执行代码,达到使用自定义generator的目的
1.首先将MBG的自定义配置文件放到resourecs或classpath中
注意配置文件的文件名与MybatisGenerator代码中的要一致,另外如果需要使用JAVA合并功能,配置文件中的
<property name="suppressAllComments" value="false" />
一定要记得设置为false,这样才能根据自定义注释中的@mbg.generated来判断哪些方法是需要被覆盖掉的
2.pom中增加自定义generator项目的依赖
<!-- ————————— 自定义MybatisGenerator ————Start————— -->
<dependency>
<!-- 改成自己的groupId和artifactId -->
<groupId>cn.xxxx</groupId>
<artifactId>dbgenerator</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<!-- ————————— 自定义MybatisGenerator ————End————— -->
3.在pom中plugins中增加执行配置
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<classpathScope>test</classpathScope>
<!-- 修改为自己定义的执行类 -->
<mainClass>cn.xxxx.dbgenerator.MybatisGenerator</mainClass>
<cleanupDaemonThreads>false</cleanupDaemonThreads>
</configuration>
</plugin>
4.通过maven的plugin执行MBG即可
另外网上的方案大部分是直接修改mybatis-generator-core代码后,打包替换本地仓库mybatis-generator-core,感觉这样时间长了容易混淆,所以还是使用了尽量不去改动开源包的方法
参考资料&感谢