diff --git a/.idea/atlassian-ide-plugin.xml b/.idea/atlassian-ide-plugin.xml
new file mode 100644
index 0000000..b68e35d
--- /dev/null
+++ b/.idea/atlassian-ide-plugin.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..6560a98
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/lib.xml b/.idea/libraries/lib.xml
new file mode 100644
index 0000000..036a8f8
--- /dev/null
+++ b/.idea/libraries/lib.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/mybatis_generator_lombok_plugin_1_1_SNAPSHOT.xml b/.idea/libraries/mybatis_generator_lombok_plugin_1_1_SNAPSHOT.xml
new file mode 100644
index 0000000..a29a3cc
--- /dev/null
+++ b/.idea/libraries/mybatis_generator_lombok_plugin_1_1_SNAPSHOT.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..7410e3d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..3aff242
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..e96534f
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..780c9c8
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,1157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ finids
+ finish
+ example
+ mapperNameField
+ mapperName
+ setDomainObjectName
+ Username
+ tableNameField
+ gene
+ connectionConfig
+ driverClass
+ mybatis generator pl
+ Line
+ resource
+ xmlpa
+ setXmlPackage
+ xmlPackageField
+ exam
+ test
+ ge
+ valid
+ myInfo
+ testcon
+ connect
+ password
+ Node
+ ovew
+ overrideXML
+ entityPackageField
+ Mybatis Generator
+
+
+ 200
+ Mybatis Generator Plus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1538367023154
+
+
+ 1538367023154
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1539142143010
+
+
+
+ 1539142143010
+
+
+ 1539162647124
+
+
+
+ 1539162647124
+
+
+ 1539162882379
+
+
+
+ 1539162882379
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ e.printStackTrace();
+ JAVA
+ EXPRESSION
+
+
+ hyperlinkEvent.getSourceElement()
+ JAVA
+ EXPRESSION
+
+
+ hyperlinkEvent.getSourceElement().getAttributes().getAttributeNames().nextElement()
+ JAVA
+ EXPRESSION
+
+
+ hyperlinkEvent.getSourceElement().getAttributes().getAttributeNames()
+ JAVA
+ EXPRESSION
+
+
+ hyperlinkEvent.getSourceElement().getAttributes()
+ JAVA
+ EXPRESSION
+
+
+ hyperlinkEvent.getSourceElement().getAttributes().getAttribute("href")
+ JAVA
+ EXPRESSION
+
+
+ hyperlinkEvent.getSourceElement().getAttributes();
+ JAVA
+ EXPRESSION
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No facets are configured
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.8
+
+
+
+
+
+
+
+
+
+
+
+ mybatis-generator-plus
+
+
+
+
+
+
+
+
+
+
+
+ 1.8
+
+
+
+
+
+
+
+
+
+
+
+ javaparser-core-3.6.25
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4f69cef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+# MyBatis Generator Plus
+一款与Idea无缝集成的好用的MyBatis生成器
+## 特性:
+- 与Idea DataSource插件集成,操作方便
+- 提供UI界面对Java代码路径,XML文件路径进行配置
+- 提供增强选项,可以选择分页、Lombok等功能
+- 支持合并Mapper文件和Xml文件,可以放心修改原来的Mapper文件,无需担心被覆盖
+
+## 操作手册
+- 在idea中建立数据库
+- 选中要生成的表右键点击弹出菜单,选择 "Generator Mybatis Code"
+ ![avatar](screenshots/20181206172856.png)
+
+- 在弹出的界面中进行生成配置:
+ ![avatar](screenshots/20181206172726.png)
+
+- 首次生成需要配置数据库密码:
+ ![avatar](screenshots/20181206172740.png)
+
+- 配置好之后点击OK生成代码,生成后右下角弹出提示,可以点击文件快速预览
+ ![avatar](screenshots/20181206172825.png)
+
+## 如何安装
+下载根目录下文件:mybatis-generator-plus.zip进行安装
\ No newline at end of file
diff --git a/mybatis-generator-plus.iml b/mybatis-generator-plus.iml
new file mode 100644
index 0000000..3065684
--- /dev/null
+++ b/mybatis-generator-plus.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mybatis-generator-plus.zip b/mybatis-generator-plus.zip
new file mode 100644
index 0000000..f53a641
Binary files /dev/null and b/mybatis-generator-plus.zip differ
diff --git a/screenshots/20181206172726.png b/screenshots/20181206172726.png
new file mode 100644
index 0000000..e602387
Binary files /dev/null and b/screenshots/20181206172726.png differ
diff --git a/screenshots/20181206172740.png b/screenshots/20181206172740.png
new file mode 100644
index 0000000..8663ac3
Binary files /dev/null and b/screenshots/20181206172740.png differ
diff --git a/screenshots/20181206172825.png b/screenshots/20181206172825.png
new file mode 100644
index 0000000..9e9619e
Binary files /dev/null and b/screenshots/20181206172825.png differ
diff --git a/screenshots/20181206172856.png b/screenshots/20181206172856.png
new file mode 100644
index 0000000..37d92bb
Binary files /dev/null and b/screenshots/20181206172856.png differ
diff --git a/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MergeableShellCallback.java b/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MergeableShellCallback.java
index 7d5dd35..4eeda35 100644
--- a/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MergeableShellCallback.java
+++ b/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MergeableShellCallback.java
@@ -1,6 +1,6 @@
package com.github.leecho.idea.plugin.mybatis.generator.generate;
-import com.github.leecho.idea.plugin.mybatis.generator.util.MapperFileMerger;
+import com.github.leecho.idea.plugin.mybatis.generator.util.JavaFileMerger;
import org.mybatis.generator.exception.ShellException;
import org.mybatis.generator.internal.DefaultShellCallback;
@@ -25,7 +25,7 @@ public String mergeJavaFile(String newFileSource, String existingFileFullPath, S
String filePath = existingFileFullPath.replace(".java", "");
if (filePath.endsWith("Mapper")) {
try {
- return new MapperFileMerger().getNewJavaFile(newFileSource, existingFileFullPath);
+ return new JavaFileMerger().getNewJavaFile(newFileSource, existingFileFullPath);
} catch (FileNotFoundException e) {
throw new ShellException(e);
}
diff --git a/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisCodeGenerator.java b/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisCodeGenerator.java
index 3db155f..8da10fe 100644
--- a/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisCodeGenerator.java
+++ b/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisCodeGenerator.java
@@ -1,562 +1,442 @@
package com.github.leecho.idea.plugin.mybatis.generator.generate;
-import cn.kt.DbRemarksCommentGenerator;
-import com.intellij.credentialStore.CredentialAttributes;
-import com.intellij.database.model.RawConnectionConfig;
-import com.intellij.ide.passwordSafe.PasswordSafe;
-import com.intellij.notification.*;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.MessageType;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.wm.StatusBar;
-import com.intellij.openapi.wm.WindowManager;
-import com.intellij.ui.awt.RelativePoint;
-import com.github.leecho.idea.plugin.mybatis.generator.model.EntityConfig;
-import com.github.leecho.idea.plugin.mybatis.generator.model.Credential;
-import com.github.leecho.idea.plugin.mybatis.generator.model.DbType;
-import com.github.leecho.idea.plugin.mybatis.generator.setting.MyBatisGeneratorConfiguration;
-import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils;
-import org.mybatis.generator.api.MyBatisGenerator;
-import org.mybatis.generator.api.ShellCallback;
-import org.mybatis.generator.config.*;
-import org.mybatis.generator.internal.DefaultShellCallback;
+import static org.mybatis.generator.internal.util.ClassloaderUtility.getCustomClassloader;
+import static org.mybatis.generator.internal.util.messages.Messages.getString;
-import javax.swing.event.HyperlinkEvent;
+import java.io.BufferedWriter;
import java.io.File;
-import java.util.*;
-import java.util.stream.Collectors;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.github.leecho.idea.plugin.mybatis.generator.util.XmlFileMerger;
+import org.mybatis.generator.api.GeneratedJavaFile;
+import org.mybatis.generator.api.GeneratedXmlFile;
+import org.mybatis.generator.api.ProgressCallback;
+import org.mybatis.generator.api.ShellCallback;
+import org.mybatis.generator.codegen.RootClassInfo;
+import org.mybatis.generator.config.Configuration;
+import org.mybatis.generator.config.Context;
+import org.mybatis.generator.config.MergeConstants;
+import org.mybatis.generator.exception.InvalidConfigurationException;
+import org.mybatis.generator.exception.ShellException;
+import org.mybatis.generator.internal.DefaultShellCallback;
+import org.mybatis.generator.internal.ObjectFactory;
+import org.mybatis.generator.internal.NullProgressCallback;
/**
- * 生成mybatis相关代码
- * Created by kangtian on 2018/7/28.
+ * This class is the main interface to MyBatis generator. A typical execution of the tool involves these steps:
+ *
+ *
+ * - Create a Configuration object. The Configuration can be the result of a parsing the XML configuration file, or it
+ * can be created solely in Java.
+ * - Create a MyBatisCodeGenerator object
+ * - Call one of the generate() methods
+ *
+ *
+ * @author Jeff Butler
+ * @see org.mybatis.generator.config.xml.ConfigurationParser
*/
public class MyBatisCodeGenerator {
- //持久化的配置
- private MyBatisGeneratorConfiguration myBatisGeneratorConfiguration;
- //界面默认配置
- private EntityConfig entityConfig;
- private String username;
- //数据库类型
- private String databaseType;
- //数据库驱动
- private String driverClass;
- //数据库连接url
- private String url;
-
- public MyBatisCodeGenerator(EntityConfig entityConfig) {
- this.entityConfig = entityConfig;
- }
-
- /**
- * 自动生成的主逻辑
- *
- * @param project
- * @param connectionConfig
- * @throws Exception
- */
- public void execute(Project project, RawConnectionConfig connectionConfig) {
- this.myBatisGeneratorConfiguration = MyBatisGeneratorConfiguration.getInstance(project);
-
- saveConfig();//执行前 先保存一份当前配置
-
- driverClass = connectionConfig.getDriverClass();
- url = connectionConfig.getUrl();
- if (driverClass.contains("mysql")) {
- databaseType = "MySQL";
- } else if (driverClass.contains("oracle")) {
- databaseType = "Oracle";
- } else if (driverClass.contains("postgresql")) {
- databaseType = "PostgreSQL";
- } else if (driverClass.contains("sqlserver")) {
- databaseType = "SqlServer";
- } else if (driverClass.contains("sqlite")) {
- databaseType = "Sqlite";
- } else if (driverClass.contains("mariadb")) {
- databaseType = "MariaDB";
- }
-
-
- Configuration configuration = new Configuration();
- Context context = new Context(ModelType.CONDITIONAL);
- configuration.addContext(context);
-
- context.setId("myid");
- context.addProperty("autoDelimitKeywords", "true");
- context.addProperty("beginningDelimiter", "`");
- context.addProperty("endingDelimiter", "`");
- context.addProperty("javaFileEncoding", "UTF-8");
- context.addProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING, "UTF-8");
- context.setTargetRuntime("MyBatis3");
-
- JDBCConnectionConfiguration jdbcConfig = buildJdbcConfig();
- if (jdbcConfig == null) {
- return;
- }
- TableConfiguration tableConfig = buildTableConfig(context);
- JavaModelGeneratorConfiguration modelConfig = buildModelConfig();
- SqlMapGeneratorConfiguration mapperConfig = buildMapperXmlConfig();
- JavaClientGeneratorConfiguration daoConfig = buildMapperConfig();
- CommentGeneratorConfiguration commentConfig = buildCommentConfig();
-
- context.addTableConfiguration(tableConfig);
- context.setJdbcConnectionConfiguration(jdbcConfig);
- context.setJavaModelGeneratorConfiguration(modelConfig);
- context.setSqlMapGeneratorConfiguration(mapperConfig);
- context.setJavaClientGeneratorConfiguration(daoConfig);
- context.setCommentGeneratorConfiguration(commentConfig);
- addPluginConfiguration(context);
-
- createFolderForNeed(entityConfig);
- List warnings = new ArrayList<>();
- // override=true
- ShellCallback shellCallback;
- if (entityConfig.isOverride()) {
- shellCallback = new DefaultShellCallback(true);
- } else {
- shellCallback = new MergeableShellCallback(false);
- }
- Set fullyQualifiedTables = new HashSet<>();
- Set contexts = new HashSet<>();
-
- try {
- MyBatisGenerator myBatisGenerator = new MyBatisGenerator(configuration, shellCallback, warnings);
- StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
- Balloon balloon = JBPopupFactory.getInstance()
- .createHtmlTextBalloonBuilder("Generating Code...", MessageType.INFO, null)
- .createBalloon();
- balloon.show(RelativePoint.getCenterOf(statusBar.getComponent()), Balloon.Position.atRight);
-
- Task.Backgroundable generateTask = new Task.Backgroundable(project, "Generating MyBatis Code", false) {
- @Override
- public void run(ProgressIndicator indicator) {
- indicator.setText("Generating MyBatis Code");
- indicator.setFraction(0.0);
- indicator.setIndeterminate(true);
- try {
- myBatisGenerator.generate(new GenerateCallback(indicator, balloon), contexts, fullyQualifiedTables);
- VirtualFile baseDir = project.getBaseDir();
- baseDir.refresh(false, true);
-
- NotificationGroup balloonNotifications = new NotificationGroup("Mybatis Generator Plus", NotificationDisplayType.STICKY_BALLOON, true);
-
- List result = myBatisGenerator.getGeneratedJavaFiles().stream()
- .map(generatedJavaFile -> String.format("%s", getRelativePath(project), entityConfig.getSourcePath(), generatedJavaFile.getTargetPackage().replace(".", "/"), generatedJavaFile.getFileName(), generatedJavaFile.getFileName()))
- .collect(Collectors.toList());
- result.addAll(myBatisGenerator.getGeneratedXmlFiles().stream()
- .map(generatedXmlFile -> String.format("%s", getRelativePath(project).replace(project.getBasePath() + "/", ""), entityConfig.getResourcePath(), generatedXmlFile.getTargetPackage().replace(".", "/"), generatedXmlFile.getFileName(), generatedXmlFile.getFileName()))
- .collect(Collectors.toList()));
- System.out.println(result);
- Notification notification = balloonNotifications.createNotification("Generate Finished", "" + String.join("
", result) + "", NotificationType.INFORMATION, (notification1, hyperlinkEvent) -> {
- if (hyperlinkEvent.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- new OpenFileDescriptor(project, Objects.requireNonNull(project.getBaseDir().findFileByRelativePath(hyperlinkEvent.getDescription()))).navigate(true);
- }
- });
- Notifications.Bus.notify(notification);
- } catch (Exception e) {
- e.printStackTrace();
- balloon.hide();
- Notification notification = new Notification("Mybatis Generator Plus", null, NotificationType.ERROR);
- notification.setTitle("Generate Code Failed");
- notification.setContent("Cause:" + e.getMessage());
- Notifications.Bus.notify(notification);
- }
- }
- };
- generateTask.setCancelText("Stop generate code").queue();
- generateTask.setCancelTooltipText("Stop generate mybatis code");
-
- } catch (Exception e) {
- e.printStackTrace();
- Messages.showMessageDialog(e.getMessage(), "Generate Failure", Messages.getInformationIcon());
- }
-
- }
-
- private String getRelativePath(Project project) {
- if (entityConfig.getProjectRootPath().equals(project.getBasePath())) {
- return "";
- } else {
- return entityConfig.getProjectRootPath().replace(project.getBasePath() + "/", "") + "/";
- }
- }
-
-
- /**
- * 创建所需目录
- *
- * @param entityConfig
- */
- private void createFolderForNeed(EntityConfig entityConfig) {
-
-
- String sourcePath = entityConfig.getProjectRootPath() + "/" + entityConfig.getSourcePath() + "/";
- String resourcePath = entityConfig.getProjectRootPath() + "/" + entityConfig.getResourcePath() + "/";
-
- File sourceFile = new File(sourcePath);
- if (!sourceFile.exists() && !sourceFile.isDirectory()) {
- sourceFile.mkdirs();
- }
-
- File resourceFile = new File(resourcePath);
- if (!resourceFile.exists() && !resourceFile.isDirectory()) {
- resourceFile.mkdirs();
- }
- }
-
-
- /**
- * 保存当前配置到历史记录
- */
- private void saveConfig() {
- Map historyConfigList = myBatisGeneratorConfiguration.getEntityConfigs();
- if (historyConfigList == null) {
- historyConfigList = new HashMap<>();
- }
-
- String daoName = entityConfig.getMapperName();
- String modelName = entityConfig.getEntityName();
- String daoPostfix = daoName.replace(modelName, "");
- entityConfig.setMapperPostfix(daoPostfix);
-
- historyConfigList.put(entityConfig.getName(), entityConfig);
- myBatisGeneratorConfiguration.setEntityConfigs(historyConfigList);
-
- }
-
- /**
- * 生成数据库连接配置
- *
- * @return
- */
- private JDBCConnectionConfiguration buildJdbcConfig() {
-
- JDBCConnectionConfiguration jdbcConfig = new JDBCConnectionConfiguration();
- jdbcConfig.addProperty("nullCatalogMeansCurrent", "true");
-
-
- Map users = myBatisGeneratorConfiguration.getCredentials();
- //if (users != null && users.containsKey(url)) {
- Credential credential = users.get(url);
-
- username = credential.getUsername();
-
- CredentialAttributes credentialAttributes = new CredentialAttributes("mybatis-generator-" + url, username, this.getClass(), false);
- String password = PasswordSafe.getInstance().getPassword(credentialAttributes);
-
- jdbcConfig.setUserId(username);
- jdbcConfig.setPassword(password);
-
- Boolean mySQL_8 = entityConfig.isMysql8();
- if (mySQL_8) {
- driverClass = DbType.MySQL_8.getDriverClass();
- url += "?serverTimezone=UTC&useSSL=false";
- } else {
- url += "?useSSL=false";
- }
-
- jdbcConfig.setDriverClass(driverClass);
- jdbcConfig.setConnectionURL(url);
- return jdbcConfig;
- /*} else {
- DatabaseCredentialUI databaseCredentialUI = new DatabaseCredentialUI(driverClass, url, anActionEvent, entityConfig);
- return null;
- }*/
-
- }
-
- /**
- * 生成table配置
- *
- * @param context
- * @return
- */
- private TableConfiguration buildTableConfig(Context context) {
- TableConfiguration tableConfig = new TableConfiguration(context);
- tableConfig.setTableName(entityConfig.getTableName());
- tableConfig.setDomainObjectName(entityConfig.getEntityName());
-
- String schema;
- if (databaseType.equals(DbType.MySQL.name())) {
- String[] name_split = url.split("/");
- schema = name_split[name_split.length - 1];
- tableConfig.setSchema(schema);
- } else if (databaseType.equals(DbType.Oracle.name())) {
- String[] name_split = url.split(":");
- schema = name_split[name_split.length - 1];
- tableConfig.setCatalog(schema);
- } else {
- String[] name_split = url.split("/");
- schema = name_split[name_split.length - 1];
- tableConfig.setCatalog(schema);
- }
-
- if (!entityConfig.isUseExample()) {
- tableConfig.setUpdateByExampleStatementEnabled(false);
- tableConfig.setCountByExampleStatementEnabled(false);
- tableConfig.setDeleteByExampleStatementEnabled(false);
- tableConfig.setSelectByExampleStatementEnabled(false);
- }
-
- if (entityConfig.isUseSchemaPrefix()) {
- if (DbType.MySQL.name().equals(databaseType)) {
- tableConfig.setSchema(schema);
- } else if (DbType.Oracle.name().equals(databaseType)) {
- //Oracle的schema为用户名,如果连接用户拥有dba等高级权限,若不设schema,会导致把其他用户下同名的表也生成一遍导致mapper中代码重复
- tableConfig.setSchema(username);
- } else {
- tableConfig.setCatalog(schema);
- }
- }
-
- if ("org.postgresql.Driver".equals(driverClass)) {
- tableConfig.setDelimitIdentifiers(true);
- }
-
- if (!StringUtils.isEmpty(entityConfig.getPrimaryKey())) {
- String dbType = databaseType;
- if (DbType.MySQL.name().equals(databaseType)) {
- dbType = "JDBC";
- //dbType为JDBC,且配置中开启useGeneratedKeys时,Mybatis会使用Jdbc3KeyGenerator,
- //使用该KeyGenerator的好处就是直接在一次INSERT 语句内,通过resultSet获取得到 生成的主键值,
- //并很好的支持设置了读写分离代理的数据库
- //例如阿里云RDS + 读写分离代理 无需指定主库
- //当使用SelectKey时,Mybatis会使用SelectKeyGenerator,INSERT之后,多发送一次查询语句,获得主键值
- //在上述读写分离被代理的情况下,会得不到正确的主键
- }
- tableConfig.setGeneratedKey(new GeneratedKey(entityConfig.getPrimaryKey(), dbType, true, null));
- }
-
- if (entityConfig.isUseActualColumnNames()) {
- tableConfig.addProperty("useActualColumnNames", "true");
- }
-
- if (entityConfig.isUseTableNameAlias()) {
- tableConfig.setAlias(entityConfig.getTableName());
- }
- tableConfig.setMapperName(entityConfig.getMapperName());
- return tableConfig;
- }
-
-
- /**
- * 生成实体类配置
- *
- * @return
- */
- private JavaModelGeneratorConfiguration buildModelConfig() {
- String projectFolder = entityConfig.getProjectRootPath();
- String entityPackage = entityConfig.getEntityPackage();
- String sourcePath = entityConfig.getSourcePath();
-
- JavaModelGeneratorConfiguration modelConfig = new JavaModelGeneratorConfiguration();
-
- if (!StringUtils.isEmpty(entityPackage)) {
- modelConfig.setTargetPackage(entityPackage);
- } else {
- modelConfig.setTargetPackage("");
- }
- modelConfig.setTargetProject(projectFolder + "/" + sourcePath + "/");
- return modelConfig;
- }
-
- /**
- * 生成mapper.xml文件配置
- *
- * @return
- */
- private SqlMapGeneratorConfiguration buildMapperXmlConfig() {
-
- String projectFolder = entityConfig.getProjectRootPath();
- String mappingXMLPackage = entityConfig.getXmlPackage();
- String resourcePath = entityConfig.getResourcePath();
-
- SqlMapGeneratorConfiguration mapperConfig = new SqlMapGeneratorConfiguration();
-
- if (!StringUtils.isEmpty(mappingXMLPackage)) {
- mapperConfig.setTargetPackage(mappingXMLPackage);
- } else {
- mapperConfig.setTargetPackage("");
- }
-
- mapperConfig.setTargetProject(projectFolder + "/" + resourcePath + "/");
-
- //14
- if (entityConfig.isOverride()) {
- String mappingXMLFilePath = getMappingXMLFilePath(entityConfig);
- File mappingXMLFile = new File(mappingXMLFilePath);
- if (mappingXMLFile.exists()) {
- mappingXMLFile.delete();
- }
- }
-
- return mapperConfig;
- }
-
- /**
- * 生成dao接口文件配置
- *
- * @return
- */
- private JavaClientGeneratorConfiguration buildMapperConfig() {
-
- String projectFolder = entityConfig.getProjectRootPath();
- String mapperPackage = entityConfig.getMapperPackage();
- String mapperPath = entityConfig.getSourcePath();
-
- JavaClientGeneratorConfiguration mapperConfig = new JavaClientGeneratorConfiguration();
- mapperConfig.setConfigurationType("XMLMAPPER");
- mapperConfig.setTargetPackage(mapperPackage);
-
- if (!StringUtils.isEmpty(mapperPackage)) {
- mapperConfig.setTargetPackage(mapperPackage);
- } else {
- mapperConfig.setTargetPackage("");
- }
-
- mapperConfig.setTargetProject(projectFolder + "/" + mapperPath + "/");
-
- return mapperConfig;
- }
-
- /**
- * 生成注释配置
- *
- * @return
- */
- private CommentGeneratorConfiguration buildCommentConfig() {
- CommentGeneratorConfiguration commentConfig = new CommentGeneratorConfiguration();
- commentConfig.setConfigurationType(DbRemarksCommentGenerator.class.getName());
-
- if (entityConfig.isComment()) {
- commentConfig.addProperty("columnRemarks", "true");
- }
- if (entityConfig.isAnnotation()) {
- commentConfig.addProperty("annotations", "true");
- }
-
- return commentConfig;
- }
-
- /**
- * 添加相关插件(注意插件文件需要通过jar引入)
- *
- * @param context
- */
- private void addPluginConfiguration(Context context) {
-
-
- //实体添加序列化
- PluginConfiguration serializablePlugin = new PluginConfiguration();
- serializablePlugin.addProperty("type", "org.mybatis.generator.plugins.SerializablePlugin");
- serializablePlugin.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin");
- context.addPluginConfiguration(serializablePlugin);
-
-
- if (entityConfig.isNeedToStringHashcodeEquals()) {
- PluginConfiguration equalsHashCodePlugin = new PluginConfiguration();
- equalsHashCodePlugin.addProperty("type", "org.mybatis.generator.plugins.EqualsHashCodePlugin");
- equalsHashCodePlugin.setConfigurationType("org.mybatis.generator.plugins.EqualsHashCodePlugin");
- context.addPluginConfiguration(equalsHashCodePlugin);
- PluginConfiguration toStringPluginPlugin = new PluginConfiguration();
- toStringPluginPlugin.addProperty("type", "org.mybatis.generator.plugins.ToStringPlugin");
- toStringPluginPlugin.setConfigurationType("org.mybatis.generator.plugins.ToStringPlugin");
- context.addPluginConfiguration(toStringPluginPlugin);
- }
-
- if (entityConfig.isLombokAnnotation()) {
- PluginConfiguration lombokPlugin = new PluginConfiguration();
- lombokPlugin.addProperty("type", "com.softwareloop.mybatis.generator.plugins.LombokPlugin");
- lombokPlugin.setConfigurationType("com.softwareloop.mybatis.generator.plugins.LombokPlugin");
- if (entityConfig.isLombokBuilderAnnotation()) {
- lombokPlugin.addProperty("builder", "true");
- lombokPlugin.addProperty("allArgsConstructor", "true");
- lombokPlugin.addProperty("noArgsConstructor", "true");
- }
- context.addPluginConfiguration(lombokPlugin);
- }
-
-
- // limit/offset插件
- if (entityConfig.isOffsetLimit()) {
- if (DbType.MySQL.name().equals(databaseType)
- || DbType.PostgreSQL.name().equals(databaseType)) {
- PluginConfiguration mySQLLimitPlugin = new PluginConfiguration();
- mySQLLimitPlugin.addProperty("type", "cn.kt.MySQLLimitPlugin");
- mySQLLimitPlugin.setConfigurationType("cn.kt.MySQLLimitPlugin");
- context.addPluginConfiguration(mySQLLimitPlugin);
- }
- }
-
- //for JSR310
- if (entityConfig.isJsr310Support()) {
- JavaTypeResolverConfiguration javaTypeResolverPlugin = new JavaTypeResolverConfiguration();
- javaTypeResolverPlugin.setConfigurationType("cn.kt.JavaTypeResolverJsr310Impl");
- context.setJavaTypeResolverConfiguration(javaTypeResolverPlugin);
- }
-
- //forUpdate 插件
- if (entityConfig.isNeedForUpdate()) {
- if (DbType.MySQL.name().equals(databaseType)
- || DbType.PostgreSQL.name().equals(databaseType)) {
- PluginConfiguration mySQLForUpdatePlugin = new PluginConfiguration();
- mySQLForUpdatePlugin.addProperty("type", "cn.kt.MySQLForUpdatePlugin");
- mySQLForUpdatePlugin.setConfigurationType("cn.kt.MySQLForUpdatePlugin");
- context.addPluginConfiguration(mySQLForUpdatePlugin);
- }
- }
-
- //repository 插件
- if (entityConfig.isAnnotationDAO()) {
- if (DbType.MySQL.name().equals(databaseType)
- || DbType.PostgreSQL.name().equals(databaseType)) {
- PluginConfiguration repositoryPlugin = new PluginConfiguration();
- repositoryPlugin.addProperty("type", "cn.kt.RepositoryPlugin");
- repositoryPlugin.setConfigurationType("cn.kt.RepositoryPlugin");
- context.addPluginConfiguration(repositoryPlugin);
- }
- }
-
- //13
- if (entityConfig.isUseDAOExtendStyle()) {
- if (DbType.MySQL.name().equals(databaseType)
- || DbType.PostgreSQL.name().equals(databaseType)) {
- PluginConfiguration commonDAOInterfacePlugin = new PluginConfiguration();
- commonDAOInterfacePlugin.addProperty("type", "cn.kt.CommonDAOInterfacePlugin");
- commonDAOInterfacePlugin.setConfigurationType("cn.kt.CommonDAOInterfacePlugin");
- context.addPluginConfiguration(commonDAOInterfacePlugin);
- }
- }
-
- }
-
- /**
- * 获取xml文件路径 用以删除之前的xml
- *
- * @param entityConfig
- * @return
- */
- private String getMappingXMLFilePath(EntityConfig entityConfig) {
- StringBuilder sb = new StringBuilder();
- String mappingXMLPackage = entityConfig.getXmlPackage();
- String xmlMvnPath = entityConfig.getResourcePath();
- sb.append(entityConfig.getProjectRootPath() + "/" + xmlMvnPath + "/");
-
- if (!StringUtils.isEmpty(mappingXMLPackage)) {
- sb.append(mappingXMLPackage.replace(".", "/")).append("/");
- }
- if (!StringUtils.isEmpty(entityConfig.getMapperName())) {
- sb.append(entityConfig.getMapperName()).append(".xml");
- } else {
- sb.append(entityConfig.getEntityName()).append("Mapper.xml");
- }
-
- return sb.toString();
- }
-}
+ /** The configuration. */
+ private Configuration configuration;
+
+ /** The shell callback. */
+ private ShellCallback shellCallback;
+
+ /** The generated java files. */
+ private List generatedJavaFiles;
+
+ /** The generated xml files. */
+ private List generatedXmlFiles;
+
+ /** The warnings. */
+ private List warnings;
+
+ /** The projects. */
+ private Set projects;
+
+ /**
+ * Constructs a MyBatisCodeGenerator object.
+ *
+ * @param configuration
+ * The configuration for this invocation
+ * @param shellCallback
+ * an instance of a ShellCallback interface. You may specify
+ * null
in which case the DefaultShellCallback will
+ * be used.
+ * @param warnings
+ * Any warnings generated during execution will be added to this
+ * list. Warnings do not affect the running of the tool, but they
+ * may affect the results. A typical warning is an unsupported
+ * data type. In that case, the column will be ignored and
+ * generation will continue. You may specify null
if
+ * you do not want warnings returned.
+ * @throws InvalidConfigurationException
+ * if the specified configuration is invalid
+ */
+ public MyBatisCodeGenerator(Configuration configuration, ShellCallback shellCallback,
+ List warnings) throws InvalidConfigurationException {
+ super();
+ if (configuration == null) {
+ throw new IllegalArgumentException(getString("RuntimeError.2")); //$NON-NLS-1$
+ } 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;
+ }
+ generatedJavaFiles = new ArrayList();
+ generatedXmlFiles = new ArrayList();
+ projects = new HashSet();
+
+ this.configuration.validate();
+ }
+
+ /**
+ * This is the main method for generating code. This method is long running, but progress can be provided and the
+ * method can be canceled through the ProgressCallback interface. This version of the method runs all configured
+ * contexts.
+ *
+ * @param callback
+ * an instance of the ProgressCallback interface, or null
if you do not require progress
+ * information
+ * @throws SQLException
+ * the SQL exception
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ * @throws InterruptedException
+ * if the method is canceled through the ProgressCallback
+ */
+ public void generate(ProgressCallback callback) throws SQLException,
+ IOException, InterruptedException {
+ generate(callback, null, null, true);
+ }
+
+ /**
+ * This is the main method for generating code. This method is long running, but progress can be provided and the
+ * method can be canceled through the ProgressCallback interface.
+ *
+ * @param callback
+ * an instance of the ProgressCallback interface, or null
if you do not require progress
+ * information
+ * @param contextIds
+ * a set of Strings containing context ids to run. Only the contexts with an id specified in this list
+ * will be run. If the list is null or empty, than all contexts are run.
+ * @throws SQLException
+ * the SQL exception
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ * @throws InterruptedException
+ * if the method is canceled through the ProgressCallback
+ */
+ public void generate(ProgressCallback callback, Set contextIds)
+ throws SQLException, IOException, InterruptedException {
+ generate(callback, contextIds, null, true);
+ }
+
+ /**
+ * This is the main method for generating code. This method is long running, but progress can be provided and the
+ * method can be cancelled through the ProgressCallback interface.
+ *
+ * @param callback
+ * an instance of the ProgressCallback interface, or null
if you do not require progress
+ * information
+ * @param contextIds
+ * a set of Strings containing context ids to run. Only the contexts with an id specified in this list
+ * will be run. If the list is null or empty, than all contexts are run.
+ * @param fullyQualifiedTableNames
+ * a set of table names to generate. The elements of the set must be Strings that exactly match what's
+ * specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully
+ * qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration
+ * will be used for code generation.
+ * @throws SQLException
+ * the SQL exception
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ * @throws InterruptedException
+ * if the method is canceled through the ProgressCallback
+ */
+ public void generate(ProgressCallback callback, Set contextIds,
+ Set fullyQualifiedTableNames) throws SQLException,
+ IOException, InterruptedException {
+ generate(callback, contextIds, fullyQualifiedTableNames, true);
+ }
+
+ /**
+ * This is the main method for generating code. This method is long running, but progress can be provided and the
+ * method can be cancelled through the ProgressCallback interface.
+ *
+ * @param callback
+ * an instance of the ProgressCallback interface, or null
if you do not require progress
+ * information
+ * @param contextIds
+ * a set of Strings containing context ids to run. Only the contexts with an id specified in this list
+ * will be run. If the list is null or empty, than all contexts are run.
+ * @param fullyQualifiedTableNames
+ * a set of table names to generate. The elements of the set must be Strings that exactly match what's
+ * specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully
+ * qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration
+ * will be used for code generation.
+ * @param writeFiles
+ * if true, then the generated files will be written to disk. If false,
+ * then the generator runs but nothing is written
+ * @throws SQLException
+ * the SQL exception
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ * @throws InterruptedException
+ * if the method is canceled through the ProgressCallback
+ */
+ public void generate(ProgressCallback callback, Set contextIds,
+ Set fullyQualifiedTableNames, boolean writeFiles) throws SQLException,
+ IOException, InterruptedException {
+
+ if (callback == null) {
+ callback = new NullProgressCallback();
+ }
+
+ generatedJavaFiles.clear();
+ generatedXmlFiles.clear();
+ ObjectFactory.reset();
+ RootClassInfo.reset();
+
+ // calculate the contexts to run
+ List contextsToRun;
+ if (contextIds == null || contextIds.size() == 0) {
+ contextsToRun = configuration.getContexts();
+ } else {
+ contextsToRun = new ArrayList();
+ for (Context context : configuration.getContexts()) {
+ if (contextIds.contains(context.getId())) {
+ contextsToRun.add(context);
+ }
+ }
+ }
+
+ // setup custom classloader if required
+ if (configuration.getClassPathEntries().size() > 0) {
+ ClassLoader classLoader = getCustomClassloader(configuration.getClassPathEntries());
+ ObjectFactory.addExternalClassLoader(classLoader);
+ }
+
+ // now run the introspections...
+ int totalSteps = 0;
+ for (Context context : contextsToRun) {
+ totalSteps += context.getIntrospectionSteps();
+ }
+ callback.introspectionStarted(totalSteps);
+
+ for (Context context : contextsToRun) {
+ context.introspectTables(callback, warnings,
+ fullyQualifiedTableNames);
+ }
+
+ // now run the generates
+ totalSteps = 0;
+ for (Context context : contextsToRun) {
+ totalSteps += context.getGenerationSteps();
+ }
+ callback.generationStarted(totalSteps);
+
+ for (Context context : contextsToRun) {
+ context.generateFiles(callback, generatedJavaFiles,
+ generatedXmlFiles, warnings);
+ }
+
+ // now save the files
+ if (writeFiles) {
+ callback.saveStarted(generatedXmlFiles.size()
+ + generatedJavaFiles.size());
+
+ for (GeneratedXmlFile gxf : generatedXmlFiles) {
+ projects.add(gxf.getTargetProject());
+ writeGeneratedXmlFile(gxf, callback);
+ }
+
+ for (GeneratedJavaFile gjf : generatedJavaFiles) {
+ projects.add(gjf.getTargetProject());
+ writeGeneratedJavaFile(gjf, callback);
+ }
+
+ for (String project : projects) {
+ shellCallback.refreshProject(project);
+ }
+ }
+
+ callback.done();
+ }
+
+ private void writeGeneratedJavaFile(GeneratedJavaFile gjf, ProgressCallback callback)
+ throws InterruptedException, IOException {
+ File targetFile;
+ String source;
+ try {
+ File directory = shellCallback.getDirectory(gjf
+ .getTargetProject(), gjf.getTargetPackage());
+ targetFile = new File(directory, gjf.getFileName());
+ if (targetFile.exists()) {
+ if (shellCallback.isMergeSupported()) {
+ source = shellCallback.mergeJavaFile(gjf
+ .getFormattedContent(), targetFile
+ .getAbsolutePath(),
+ MergeConstants.OLD_ELEMENT_TAGS,
+ gjf.getFileEncoding());
+ } else if (shellCallback.isOverwriteEnabled()) {
+ source = gjf.getFormattedContent();
+ warnings.add(getString("Warning.11", //$NON-NLS-1$
+ targetFile.getAbsolutePath()));
+ } else {
+ source = gjf.getFormattedContent();
+ targetFile = getUniqueFileName(directory, gjf
+ .getFileName());
+ warnings.add(getString(
+ "Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$
+ }
+ } else {
+ source = gjf.getFormattedContent();
+ }
+
+ callback.checkCancel();
+ callback.startTask(getString(
+ "Progress.15", targetFile.getName())); //$NON-NLS-1$
+ writeFile(targetFile, source, gjf.getFileEncoding());
+ } catch (ShellException e) {
+ warnings.add(e.getMessage());
+ }
+ }
+
+ private void writeGeneratedXmlFile(GeneratedXmlFile gxf, ProgressCallback callback)
+ throws InterruptedException, IOException {
+ File targetFile;
+ String source;
+ try {
+ File directory = shellCallback.getDirectory(gxf
+ .getTargetProject(), gxf.getTargetPackage());
+ targetFile = new File(directory, gxf.getFileName());
+ if (targetFile.exists()) {
+ if (gxf.isMergeable()) {
+ source = XmlFileMerger.getMergedSource(gxf,
+ targetFile);
+ } else if (shellCallback.isOverwriteEnabled()) {
+ source = gxf.getFormattedContent();
+ warnings.add(getString("Warning.11", //$NON-NLS-1$
+ targetFile.getAbsolutePath()));
+ } else {
+ source = gxf.getFormattedContent();
+ targetFile = getUniqueFileName(directory, gxf
+ .getFileName());
+ warnings.add(getString(
+ "Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$
+ }
+ } else {
+ source = gxf.getFormattedContent();
+ }
+
+ callback.checkCancel();
+ callback.startTask(getString(
+ "Progress.15", targetFile.getName())); //$NON-NLS-1$
+ writeFile(targetFile, source, "UTF-8"); //$NON-NLS-1$
+ } catch (ShellException e) {
+ warnings.add(e.getMessage());
+ }
+ }
+
+ /**
+ * Writes, or overwrites, the contents of the specified file.
+ *
+ * @param file
+ * the file
+ * @param content
+ * the content
+ * @param fileEncoding
+ * the file encoding
+ * @throws IOException
+ * Signals that an I/O exception has occurred.
+ */
+ private void writeFile(File file, String content, String fileEncoding) throws IOException {
+ FileOutputStream fos = new FileOutputStream(file, false);
+ OutputStreamWriter osw;
+ if (fileEncoding == null) {
+ osw = new OutputStreamWriter(fos);
+ } else {
+ osw = new OutputStreamWriter(fos, fileEncoding);
+ }
+
+ BufferedWriter bw = new BufferedWriter(osw);
+ bw.write(content);
+ bw.close();
+ }
+
+ /**
+ * Gets the unique file name.
+ *
+ * @param directory
+ * the directory
+ * @param fileName
+ * the file name
+ * @return the unique file name
+ */
+ private File getUniqueFileName(File directory, String fileName) {
+ File answer = null;
+
+ // try up to 1000 times to generate a unique file name
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1; i < 1000; i++) {
+ sb.setLength(0);
+ sb.append(fileName);
+ sb.append('.');
+ sb.append(i);
+
+ File testFile = new File(directory, sb.toString());
+ if (!testFile.exists()) {
+ answer = testFile;
+ break;
+ }
+ }
+
+ if (answer == null) {
+ throw new RuntimeException(getString(
+ "RuntimeError.3", directory.getAbsolutePath())); //$NON-NLS-1$
+ }
+
+ return answer;
+ }
+
+ /**
+ * Returns the list of generated Java files after a call to one of the generate methods.
+ * This is useful if you prefer to process the generated files yourself and do not want
+ * the generator to write them to disk.
+ *
+ * @return the list of generated Java files
+ */
+ public List getGeneratedJavaFiles() {
+ return generatedJavaFiles;
+ }
+
+ /**
+ * Returns the list of generated XML files after a call to one of the generate methods.
+ * This is useful if you prefer to process the generated files yourself and do not want
+ * the generator to write them to disk.
+ *
+ * @return the list of generated XML files
+ */
+ public List getGeneratedXmlFiles() {
+ return generatedXmlFiles;
+ }
+}
\ No newline at end of file
diff --git a/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisGenerateCommand.java b/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisGenerateCommand.java
new file mode 100644
index 0000000..efe16d1
--- /dev/null
+++ b/src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisGenerateCommand.java
@@ -0,0 +1,562 @@
+package com.github.leecho.idea.plugin.mybatis.generator.generate;
+
+import cn.kt.DbRemarksCommentGenerator;
+import com.intellij.credentialStore.CredentialAttributes;
+import com.intellij.database.model.RawConnectionConfig;
+import com.intellij.ide.passwordSafe.PasswordSafe;
+import com.intellij.notification.*;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.StatusBar;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.ui.awt.RelativePoint;
+import com.github.leecho.idea.plugin.mybatis.generator.model.EntityConfig;
+import com.github.leecho.idea.plugin.mybatis.generator.model.Credential;
+import com.github.leecho.idea.plugin.mybatis.generator.model.DbType;
+import com.github.leecho.idea.plugin.mybatis.generator.setting.MyBatisGeneratorConfiguration;
+import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils;
+import org.mybatis.generator.api.GeneratedXmlFile;
+import org.mybatis.generator.api.ShellCallback;
+import org.mybatis.generator.config.*;
+import org.mybatis.generator.internal.DefaultShellCallback;
+
+import javax.swing.event.HyperlinkEvent;
+import java.io.File;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 生成mybatis相关代码
+ * Created by kangtian on 2018/7/28.
+ */
+public class MyBatisGenerateCommand {
+
+ //持久化的配置
+ private MyBatisGeneratorConfiguration myBatisGeneratorConfiguration;
+ //界面默认配置
+ private EntityConfig entityConfig;
+ private String username;
+ //数据库类型
+ private String databaseType;
+ //数据库驱动
+ private String driverClass;
+ //数据库连接url
+ private String url;
+
+ public MyBatisGenerateCommand(EntityConfig entityConfig) {
+ this.entityConfig = entityConfig;
+ }
+
+ /**
+ * 自动生成的主逻辑
+ *
+ * @param project
+ * @param connectionConfig
+ * @throws Exception
+ */
+ public void execute(Project project, RawConnectionConfig connectionConfig) {
+ this.myBatisGeneratorConfiguration = MyBatisGeneratorConfiguration.getInstance(project);
+
+ saveConfig();//执行前 先保存一份当前配置
+
+ driverClass = connectionConfig.getDriverClass();
+ url = connectionConfig.getUrl();
+ if (driverClass.contains("mysql")) {
+ databaseType = "MySQL";
+ } else if (driverClass.contains("oracle")) {
+ databaseType = "Oracle";
+ } else if (driverClass.contains("postgresql")) {
+ databaseType = "PostgreSQL";
+ } else if (driverClass.contains("sqlserver")) {
+ databaseType = "SqlServer";
+ } else if (driverClass.contains("sqlite")) {
+ databaseType = "Sqlite";
+ } else if (driverClass.contains("mariadb")) {
+ databaseType = "MariaDB";
+ }
+
+
+ Configuration configuration = new Configuration();
+ Context context = new Context(ModelType.CONDITIONAL);
+ configuration.addContext(context);
+
+ context.setId("myid");
+ context.addProperty("autoDelimitKeywords", "true");
+ context.addProperty("beginningDelimiter", "`");
+ context.addProperty("endingDelimiter", "`");
+ context.addProperty("javaFileEncoding", "UTF-8");
+ context.addProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING, "UTF-8");
+ context.setTargetRuntime("MyBatis3");
+
+ JDBCConnectionConfiguration jdbcConfig = buildJdbcConfig();
+ if (jdbcConfig == null) {
+ return;
+ }
+ TableConfiguration tableConfig = buildTableConfig(context);
+ JavaModelGeneratorConfiguration modelConfig = buildModelConfig();
+ SqlMapGeneratorConfiguration mapperConfig = buildMapperXmlConfig();
+ JavaClientGeneratorConfiguration daoConfig = buildMapperConfig();
+ CommentGeneratorConfiguration commentConfig = buildCommentConfig();
+
+ context.addTableConfiguration(tableConfig);
+ context.setJdbcConnectionConfiguration(jdbcConfig);
+ context.setJavaModelGeneratorConfiguration(modelConfig);
+ context.setSqlMapGeneratorConfiguration(mapperConfig);
+ context.setJavaClientGeneratorConfiguration(daoConfig);
+ context.setCommentGeneratorConfiguration(commentConfig);
+ addPluginConfiguration(context);
+
+ createFolderForNeed(entityConfig);
+ List warnings = new ArrayList<>();
+ // override=true
+ ShellCallback shellCallback;
+ if (entityConfig.isOverride()) {
+ shellCallback = new DefaultShellCallback(true);
+ } else {
+ shellCallback = new MergeableShellCallback(true);
+ }
+ System.out.println(shellCallback);
+ Set fullyQualifiedTables = new HashSet<>();
+ Set contexts = new HashSet<>();
+
+ try {
+ MyBatisCodeGenerator myBatisCodeGenerator = new MyBatisCodeGenerator(configuration, shellCallback, warnings);
+ StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
+ Balloon balloon = JBPopupFactory.getInstance()
+ .createHtmlTextBalloonBuilder("Generating Code...", MessageType.INFO, null)
+ .createBalloon();
+ balloon.show(RelativePoint.getCenterOf(statusBar.getComponent()), Balloon.Position.atRight);
+
+ Task.Backgroundable generateTask = new Task.Backgroundable(project, "Generating MyBatis Code", false) {
+ @Override
+ public void run(ProgressIndicator indicator) {
+ indicator.setText("Generating MyBatis Code");
+ indicator.setFraction(0.0);
+ indicator.setIndeterminate(true);
+ try {
+ myBatisCodeGenerator.generate(new GenerateCallback(indicator, balloon), contexts, fullyQualifiedTables);
+ VirtualFile baseDir = project.getBaseDir();
+ baseDir.refresh(false, true);
+
+ NotificationGroup balloonNotifications = new NotificationGroup("Mybatis Generator Plus", NotificationDisplayType.STICKY_BALLOON, true);
+
+ List result = myBatisCodeGenerator.getGeneratedJavaFiles().stream()
+ .map(generatedJavaFile -> String.format("%s", getRelativePath(project), entityConfig.getSourcePath(), generatedJavaFile.getTargetPackage().replace(".", "/"), generatedJavaFile.getFileName(), generatedJavaFile.getFileName()))
+ .collect(Collectors.toList());
+ result.addAll(myBatisCodeGenerator.getGeneratedXmlFiles().stream()
+ .map(generatedXmlFile -> String.format("%s", getRelativePath(project).replace(project.getBasePath() + "/", ""), entityConfig.getResourcePath(), generatedXmlFile.getTargetPackage().replace(".", "/"), generatedXmlFile.getFileName(), generatedXmlFile.getFileName()))
+ .collect(Collectors.toList()));
+ Notification notification = balloonNotifications.createNotification("Generate Finished", "" + String.join("
", result) + "", NotificationType.INFORMATION, (notification1, hyperlinkEvent) -> {
+ if (hyperlinkEvent.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ new OpenFileDescriptor(project, Objects.requireNonNull(project.getBaseDir().findFileByRelativePath(hyperlinkEvent.getDescription()))).navigate(true);
+ }
+ });
+ Notifications.Bus.notify(notification);
+ } catch (Exception e) {
+ e.printStackTrace();
+ balloon.hide();
+ Notification notification = new Notification("Mybatis Generator Plus", null, NotificationType.ERROR);
+ notification.setTitle("Generate Code Failed");
+ notification.setContent("Cause:" + e.getMessage());
+ Notifications.Bus.notify(notification);
+ }
+ }
+ };
+ generateTask.setCancelText("Stop generate code").queue();
+ generateTask.setCancelTooltipText("Stop generate mybatis code");
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ Messages.showMessageDialog(e.getMessage(), "Generate Failure", Messages.getInformationIcon());
+ }
+
+ }
+
+ private String getRelativePath(Project project) {
+ if (entityConfig.getProjectRootPath().equals(project.getBasePath())) {
+ return "";
+ } else {
+ return entityConfig.getProjectRootPath().replace(project.getBasePath() + "/", "") + "/";
+ }
+ }
+
+
+ /**
+ * 创建所需目录
+ *
+ * @param entityConfig
+ */
+ private void createFolderForNeed(EntityConfig entityConfig) {
+
+
+ String sourcePath = entityConfig.getProjectRootPath() + "/" + entityConfig.getSourcePath() + "/";
+ String resourcePath = entityConfig.getProjectRootPath() + "/" + entityConfig.getResourcePath() + "/";
+
+ File sourceFile = new File(sourcePath);
+ if (!sourceFile.exists() && !sourceFile.isDirectory()) {
+ sourceFile.mkdirs();
+ }
+
+ File resourceFile = new File(resourcePath);
+ if (!resourceFile.exists() && !resourceFile.isDirectory()) {
+ resourceFile.mkdirs();
+ }
+ }
+
+
+ /**
+ * 保存当前配置到历史记录
+ */
+ private void saveConfig() {
+ Map historyConfigList = myBatisGeneratorConfiguration.getEntityConfigs();
+ if (historyConfigList == null) {
+ historyConfigList = new HashMap<>();
+ }
+
+ String daoName = entityConfig.getMapperName();
+ String modelName = entityConfig.getEntityName();
+ String daoPostfix = daoName.replace(modelName, "");
+ entityConfig.setMapperPostfix(daoPostfix);
+
+ historyConfigList.put(entityConfig.getName(), entityConfig);
+ myBatisGeneratorConfiguration.setEntityConfigs(historyConfigList);
+
+ }
+
+ /**
+ * 生成数据库连接配置
+ *
+ * @return
+ */
+ private JDBCConnectionConfiguration buildJdbcConfig() {
+
+ JDBCConnectionConfiguration jdbcConfig = new JDBCConnectionConfiguration();
+ jdbcConfig.addProperty("nullCatalogMeansCurrent", "true");
+
+
+ Map users = myBatisGeneratorConfiguration.getCredentials();
+ //if (users != null && users.containsKey(url)) {
+ Credential credential = users.get(url);
+
+ username = credential.getUsername();
+
+ CredentialAttributes credentialAttributes = new CredentialAttributes("mybatis-generator-" + url, username, this.getClass(), false);
+ String password = PasswordSafe.getInstance().getPassword(credentialAttributes);
+
+ jdbcConfig.setUserId(username);
+ jdbcConfig.setPassword(password);
+
+ Boolean mySQL_8 = entityConfig.isMysql8();
+ if (mySQL_8) {
+ driverClass = DbType.MySQL_8.getDriverClass();
+ url += "?serverTimezone=UTC&useSSL=false";
+ } else {
+ url += "?useSSL=false";
+ }
+
+ jdbcConfig.setDriverClass(driverClass);
+ jdbcConfig.setConnectionURL(url);
+ return jdbcConfig;
+ /*} else {
+ DatabaseCredentialUI databaseCredentialUI = new DatabaseCredentialUI(driverClass, url, anActionEvent, entityConfig);
+ return null;
+ }*/
+
+ }
+
+ /**
+ * 生成table配置
+ *
+ * @param context
+ * @return
+ */
+ private TableConfiguration buildTableConfig(Context context) {
+ TableConfiguration tableConfig = new TableConfiguration(context);
+ tableConfig.setTableName(entityConfig.getTableName());
+ tableConfig.setDomainObjectName(entityConfig.getEntityName());
+
+ String schema;
+ if (databaseType.equals(DbType.MySQL.name())) {
+ String[] name_split = url.split("/");
+ schema = name_split[name_split.length - 1];
+ tableConfig.setSchema(schema);
+ } else if (databaseType.equals(DbType.Oracle.name())) {
+ String[] name_split = url.split(":");
+ schema = name_split[name_split.length - 1];
+ tableConfig.setCatalog(schema);
+ } else {
+ String[] name_split = url.split("/");
+ schema = name_split[name_split.length - 1];
+ tableConfig.setCatalog(schema);
+ }
+
+ if (!entityConfig.isUseExample()) {
+ tableConfig.setUpdateByExampleStatementEnabled(false);
+ tableConfig.setCountByExampleStatementEnabled(false);
+ tableConfig.setDeleteByExampleStatementEnabled(false);
+ tableConfig.setSelectByExampleStatementEnabled(false);
+ }
+
+ if (entityConfig.isUseSchemaPrefix()) {
+ if (DbType.MySQL.name().equals(databaseType)) {
+ tableConfig.setSchema(schema);
+ } else if (DbType.Oracle.name().equals(databaseType)) {
+ //Oracle的schema为用户名,如果连接用户拥有dba等高级权限,若不设schema,会导致把其他用户下同名的表也生成一遍导致mapper中代码重复
+ tableConfig.setSchema(username);
+ } else {
+ tableConfig.setCatalog(schema);
+ }
+ }
+
+ if ("org.postgresql.Driver".equals(driverClass)) {
+ tableConfig.setDelimitIdentifiers(true);
+ }
+
+ if (!StringUtils.isEmpty(entityConfig.getPrimaryKey())) {
+ String dbType = databaseType;
+ if (DbType.MySQL.name().equals(databaseType)) {
+ dbType = "JDBC";
+ //dbType为JDBC,且配置中开启useGeneratedKeys时,Mybatis会使用Jdbc3KeyGenerator,
+ //使用该KeyGenerator的好处就是直接在一次INSERT 语句内,通过resultSet获取得到 生成的主键值,
+ //并很好的支持设置了读写分离代理的数据库
+ //例如阿里云RDS + 读写分离代理 无需指定主库
+ //当使用SelectKey时,Mybatis会使用SelectKeyGenerator,INSERT之后,多发送一次查询语句,获得主键值
+ //在上述读写分离被代理的情况下,会得不到正确的主键
+ }
+ tableConfig.setGeneratedKey(new GeneratedKey(entityConfig.getPrimaryKey(), dbType, true, null));
+ }
+
+ if (entityConfig.isUseActualColumnNames()) {
+ tableConfig.addProperty("useActualColumnNames", "true");
+ }
+
+ if (entityConfig.isUseTableNameAlias()) {
+ tableConfig.setAlias(entityConfig.getTableName());
+ }
+ tableConfig.setMapperName(entityConfig.getMapperName());
+ return tableConfig;
+ }
+
+
+ /**
+ * 生成实体类配置
+ *
+ * @return
+ */
+ private JavaModelGeneratorConfiguration buildModelConfig() {
+ String projectFolder = entityConfig.getProjectRootPath();
+ String entityPackage = entityConfig.getEntityPackage();
+ String sourcePath = entityConfig.getSourcePath();
+
+ JavaModelGeneratorConfiguration modelConfig = new JavaModelGeneratorConfiguration();
+
+ if (!StringUtils.isEmpty(entityPackage)) {
+ modelConfig.setTargetPackage(entityPackage);
+ } else {
+ modelConfig.setTargetPackage("");
+ }
+ modelConfig.setTargetProject(projectFolder + "/" + sourcePath + "/");
+ return modelConfig;
+ }
+
+ /**
+ * 生成mapper.xml文件配置
+ *
+ * @return
+ */
+ private SqlMapGeneratorConfiguration buildMapperXmlConfig() {
+
+ String projectFolder = entityConfig.getProjectRootPath();
+ String mappingXMLPackage = entityConfig.getXmlPackage();
+ String resourcePath = entityConfig.getResourcePath();
+
+ SqlMapGeneratorConfiguration mapperConfig = new SqlMapGeneratorConfiguration();
+
+ if (!StringUtils.isEmpty(mappingXMLPackage)) {
+ mapperConfig.setTargetPackage(mappingXMLPackage);
+ } else {
+ mapperConfig.setTargetPackage("");
+ }
+
+ mapperConfig.setTargetProject(projectFolder + "/" + resourcePath + "/");
+
+ //14
+ if (entityConfig.isOverride()) {
+ String mappingXMLFilePath = getMappingXMLFilePath(entityConfig);
+ File mappingXMLFile = new File(mappingXMLFilePath);
+ if (mappingXMLFile.exists()) {
+ mappingXMLFile.delete();
+ }
+ }
+
+ return mapperConfig;
+ }
+
+ /**
+ * 生成dao接口文件配置
+ *
+ * @return
+ */
+ private JavaClientGeneratorConfiguration buildMapperConfig() {
+
+ String projectFolder = entityConfig.getProjectRootPath();
+ String mapperPackage = entityConfig.getMapperPackage();
+ String mapperPath = entityConfig.getSourcePath();
+
+ JavaClientGeneratorConfiguration mapperConfig = new JavaClientGeneratorConfiguration();
+ mapperConfig.setConfigurationType("XMLMAPPER");
+ mapperConfig.setTargetPackage(mapperPackage);
+
+ if (!StringUtils.isEmpty(mapperPackage)) {
+ mapperConfig.setTargetPackage(mapperPackage);
+ } else {
+ mapperConfig.setTargetPackage("");
+ }
+
+ mapperConfig.setTargetProject(projectFolder + "/" + mapperPath + "/");
+
+ return mapperConfig;
+ }
+
+ /**
+ * 生成注释配置
+ *
+ * @return
+ */
+ private CommentGeneratorConfiguration buildCommentConfig() {
+ CommentGeneratorConfiguration commentConfig = new CommentGeneratorConfiguration();
+ commentConfig.setConfigurationType(DbRemarksCommentGenerator.class.getName());
+
+ if (entityConfig.isComment()) {
+ commentConfig.addProperty("columnRemarks", "true");
+ }
+ if (entityConfig.isAnnotation()) {
+ commentConfig.addProperty("annotations", "true");
+ }
+
+ return commentConfig;
+ }
+
+ /**
+ * 添加相关插件(注意插件文件需要通过jar引入)
+ *
+ * @param context
+ */
+ private void addPluginConfiguration(Context context) {
+
+
+ //实体添加序列化
+ PluginConfiguration serializablePlugin = new PluginConfiguration();
+ serializablePlugin.addProperty("type", "org.mybatis.generator.plugins.SerializablePlugin");
+ serializablePlugin.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin");
+ context.addPluginConfiguration(serializablePlugin);
+
+
+ if (entityConfig.isNeedToStringHashcodeEquals()) {
+ PluginConfiguration equalsHashCodePlugin = new PluginConfiguration();
+ equalsHashCodePlugin.addProperty("type", "org.mybatis.generator.plugins.EqualsHashCodePlugin");
+ equalsHashCodePlugin.setConfigurationType("org.mybatis.generator.plugins.EqualsHashCodePlugin");
+ context.addPluginConfiguration(equalsHashCodePlugin);
+ PluginConfiguration toStringPluginPlugin = new PluginConfiguration();
+ toStringPluginPlugin.addProperty("type", "org.mybatis.generator.plugins.ToStringPlugin");
+ toStringPluginPlugin.setConfigurationType("org.mybatis.generator.plugins.ToStringPlugin");
+ context.addPluginConfiguration(toStringPluginPlugin);
+ }
+
+ if (entityConfig.isLombokAnnotation()) {
+ PluginConfiguration lombokPlugin = new PluginConfiguration();
+ lombokPlugin.addProperty("type", "com.softwareloop.mybatis.generator.plugins.LombokPlugin");
+ lombokPlugin.setConfigurationType("com.softwareloop.mybatis.generator.plugins.LombokPlugin");
+ if (entityConfig.isLombokBuilderAnnotation()) {
+ lombokPlugin.addProperty("builder", "true");
+ lombokPlugin.addProperty("allArgsConstructor", "true");
+ lombokPlugin.addProperty("noArgsConstructor", "true");
+ }
+ context.addPluginConfiguration(lombokPlugin);
+ }
+
+
+ // limit/offset插件
+ if (entityConfig.isOffsetLimit()) {
+ if (DbType.MySQL.name().equals(databaseType)
+ || DbType.PostgreSQL.name().equals(databaseType)) {
+ PluginConfiguration mySQLLimitPlugin = new PluginConfiguration();
+ mySQLLimitPlugin.addProperty("type", "cn.kt.MySQLLimitPlugin");
+ mySQLLimitPlugin.setConfigurationType("cn.kt.MySQLLimitPlugin");
+ context.addPluginConfiguration(mySQLLimitPlugin);
+ }
+ }
+
+ //for JSR310
+ if (entityConfig.isJsr310Support()) {
+ JavaTypeResolverConfiguration javaTypeResolverPlugin = new JavaTypeResolverConfiguration();
+ javaTypeResolverPlugin.setConfigurationType("cn.kt.JavaTypeResolverJsr310Impl");
+ context.setJavaTypeResolverConfiguration(javaTypeResolverPlugin);
+ }
+
+ //forUpdate 插件
+ if (entityConfig.isNeedForUpdate()) {
+ if (DbType.MySQL.name().equals(databaseType)
+ || DbType.PostgreSQL.name().equals(databaseType)) {
+ PluginConfiguration mySQLForUpdatePlugin = new PluginConfiguration();
+ mySQLForUpdatePlugin.addProperty("type", "cn.kt.MySQLForUpdatePlugin");
+ mySQLForUpdatePlugin.setConfigurationType("cn.kt.MySQLForUpdatePlugin");
+ context.addPluginConfiguration(mySQLForUpdatePlugin);
+ }
+ }
+
+ //repository 插件
+ if (entityConfig.isAnnotationDAO()) {
+ if (DbType.MySQL.name().equals(databaseType)
+ || DbType.PostgreSQL.name().equals(databaseType)) {
+ PluginConfiguration repositoryPlugin = new PluginConfiguration();
+ repositoryPlugin.addProperty("type", "cn.kt.RepositoryPlugin");
+ repositoryPlugin.setConfigurationType("cn.kt.RepositoryPlugin");
+ context.addPluginConfiguration(repositoryPlugin);
+ }
+ }
+
+ //13
+ if (entityConfig.isUseDAOExtendStyle()) {
+ if (DbType.MySQL.name().equals(databaseType)
+ || DbType.PostgreSQL.name().equals(databaseType)) {
+ PluginConfiguration commonDAOInterfacePlugin = new PluginConfiguration();
+ commonDAOInterfacePlugin.addProperty("type", "cn.kt.CommonDAOInterfacePlugin");
+ commonDAOInterfacePlugin.setConfigurationType("cn.kt.CommonDAOInterfacePlugin");
+ context.addPluginConfiguration(commonDAOInterfacePlugin);
+ }
+ }
+
+ }
+
+ /**
+ * 获取xml文件路径 用以删除之前的xml
+ *
+ * @param entityConfig
+ * @return
+ */
+ private String getMappingXMLFilePath(EntityConfig entityConfig) {
+ StringBuilder sb = new StringBuilder();
+ String mappingXMLPackage = entityConfig.getXmlPackage();
+ String xmlMvnPath = entityConfig.getResourcePath();
+ sb.append(entityConfig.getProjectRootPath() + "/" + xmlMvnPath + "/");
+
+ if (!StringUtils.isEmpty(mappingXMLPackage)) {
+ sb.append(mappingXMLPackage.replace(".", "/")).append("/");
+ }
+ if (!StringUtils.isEmpty(entityConfig.getMapperName())) {
+ sb.append(entityConfig.getMapperName()).append(".xml");
+ } else {
+ sb.append(entityConfig.getEntityName()).append("Mapper.xml");
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/src/com/github/leecho/idea/plugin/mybatis/generator/ui/GenerateSettingUI.java b/src/com/github/leecho/idea/plugin/mybatis/generator/ui/GenerateSettingUI.java
index c63a45a..df682e6 100644
--- a/src/com/github/leecho/idea/plugin/mybatis/generator/ui/GenerateSettingUI.java
+++ b/src/com/github/leecho/idea/plugin/mybatis/generator/ui/GenerateSettingUI.java
@@ -1,7 +1,7 @@
package com.github.leecho.idea.plugin.mybatis.generator.ui;
import com.github.leecho.idea.plugin.mybatis.generator.contants.PluginContants;
-import com.github.leecho.idea.plugin.mybatis.generator.generate.MyBatisCodeGenerator;
+import com.github.leecho.idea.plugin.mybatis.generator.generate.MyBatisGenerateCommand;
import com.github.leecho.idea.plugin.mybatis.generator.model.Credential;
import com.github.leecho.idea.plugin.mybatis.generator.model.EntityConfig;
import com.github.leecho.idea.plugin.mybatis.generator.model.GlobalConfig;
@@ -509,7 +509,7 @@ public void generate(RawConnectionConfig connectionConfig) {
entityConfig.setSourcePath(this.entityConfig.getSourcePath());
entityConfig.setResourcePath(this.entityConfig.getResourcePath());
- new MyBatisCodeGenerator(entityConfig).execute(project, connectionConfig);
+ new MyBatisGenerateCommand(entityConfig).execute(project, connectionConfig);
}
diff --git a/src/com/github/leecho/idea/plugin/mybatis/generator/util/MapperFileMerger.java b/src/com/github/leecho/idea/plugin/mybatis/generator/util/JavaFileMerger.java
similarity index 98%
rename from src/com/github/leecho/idea/plugin/mybatis/generator/util/MapperFileMerger.java
rename to src/com/github/leecho/idea/plugin/mybatis/generator/util/JavaFileMerger.java
index 32a23fb..5eeb0f3 100644
--- a/src/com/github/leecho/idea/plugin/mybatis/generator/util/MapperFileMerger.java
+++ b/src/com/github/leecho/idea/plugin/mybatis/generator/util/JavaFileMerger.java
@@ -17,7 +17,7 @@
/**
* @author LIQIU
*/
-public class MapperFileMerger {
+public class JavaFileMerger {
public String getNewJavaFile(String newFileSource, String existingFileFullPath) throws FileNotFoundException {
CompilationUnit newCompilationUnit = JavaParser.parse(newFileSource);
diff --git a/src/com/github/leecho/idea/plugin/mybatis/generator/util/XmlFileMerger.java b/src/com/github/leecho/idea/plugin/mybatis/generator/util/XmlFileMerger.java
new file mode 100644
index 0000000..44a746c
--- /dev/null
+++ b/src/com/github/leecho/idea/plugin/mybatis/generator/util/XmlFileMerger.java
@@ -0,0 +1,256 @@
+package com.github.leecho.idea.plugin.mybatis.generator.util;
+
+import static org.mybatis.generator.internal.util.messages.Messages.getString;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import com.sun.org.apache.xerces.internal.dom.DeferredTextImpl;
+import org.mybatis.generator.api.GeneratedXmlFile;
+import org.mybatis.generator.config.MergeConstants;
+import org.mybatis.generator.exception.ShellException;
+import org.mybatis.generator.internal.DomWriter;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * This class handles the task of merging changes into an existing XML file.
+ *
+ * @author Jeff Butler
+ */
+public class XmlFileMerger {
+ private static class NullEntityResolver implements EntityResolver {
+ /**
+ * returns an empty reader. This is done so that the parser doesn't
+ * attempt to read a DTD. We don't need that support for the merge and
+ * it can cause problems on systems that aren't Internet connected.
+ */
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId)
+ throws SAXException, IOException {
+
+ StringReader sr = new StringReader(""); //$NON-NLS-1$
+
+ return new InputSource(sr);
+ }
+ }
+
+ /**
+ * Utility class - no instances allowed
+ */
+ private XmlFileMerger() {
+ super();
+ }
+
+ public static String getMergedSource(GeneratedXmlFile generatedXmlFile,
+ File existingFile) throws ShellException {
+
+ try {
+ return getMergedSource(new InputSource(new StringReader(generatedXmlFile.getFormattedContent())),
+ new InputSource(new InputStreamReader(new FileInputStream(existingFile), "UTF-8")), //$NON-NLS-1$
+ existingFile.getName());
+ } catch (IOException e) {
+ throw new ShellException(getString("Warning.13", //$NON-NLS-1$
+ existingFile.getName()), e);
+ } catch (SAXException e) {
+ throw new ShellException(getString("Warning.13", //$NON-NLS-1$
+ existingFile.getName()), e);
+ } catch (ParserConfigurationException e) {
+ throw new ShellException(getString("Warning.13", //$NON-NLS-1$
+ existingFile.getName()), e);
+ }
+ }
+
+ public static String getMergedSource(InputSource newFile,
+ InputSource existingFile, String existingFileName) throws IOException, SAXException,
+ ParserConfigurationException, ShellException {
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ factory.setExpandEntityReferences(false);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ builder.setEntityResolver(new NullEntityResolver());
+
+ Document existingDocument = builder.parse(existingFile);
+ Document newDocument = builder.parse(newFile);
+
+ DocumentType newDocType = newDocument.getDoctype();
+ DocumentType existingDocType = existingDocument.getDoctype();
+
+ if (!newDocType.getName().equals(existingDocType.getName())) {
+ throw new ShellException(getString("Warning.12", //$NON-NLS-1$
+ existingFileName));
+ }
+
+ Element existingRootElement = existingDocument.getDocumentElement();
+ Element newRootElement = newDocument.getDocumentElement();
+
+ // reconcile the root element attributes -
+ // take all attributes from the new element and add to the existing
+ // element
+
+ // remove all attributes from the existing root element
+ NamedNodeMap attributes = existingRootElement.getAttributes();
+ int attributeCount = attributes.getLength();
+ for (int i = attributeCount - 1; i >= 0; i--) {
+ Node node = attributes.item(i);
+ existingRootElement.removeAttribute(node.getNodeName());
+ }
+
+ // add attributes from the new root node to the old root node
+ attributes = newRootElement.getAttributes();
+ attributeCount = attributes.getLength();
+ for (int i = 0; i < attributeCount; i++) {
+ Node node = attributes.item(i);
+ existingRootElement.setAttribute(node.getNodeName(), node
+ .getNodeValue());
+ }
+
+ NodeList newMethods = newRootElement.getChildNodes();
+ List methods = new ArrayList();
+ for (int i = 0; i < newMethods.getLength(); i++) {
+ Node node = newMethods.item(i);
+ try {
+ if (node instanceof DeferredTextImpl) {
+ continue;
+ }
+ Element ele = (Element) node;
+ methods.add(ele.getAttribute("id"));
+ } catch (Exception e) {
+ //#text节点转换会异常
+ continue;
+ }
+ if (i == newMethods.getLength() - 1) {
+ if (isWhiteSpace(node)) {
+ break;
+ }
+ }
+ }
+
+ // remove the old generated elements and any
+ // white space before the old nodes
+ List nodesToDelete = new ArrayList();
+ NodeList children = existingRootElement.getChildNodes();
+ int length = children.getLength();
+ for (int i = 0; i < length; i++) {
+ Node node = children.item(i);
+ if (isGeneratedNode(node, methods)) {
+ nodesToDelete.add(node);
+ } else if (isWhiteSpace(node)
+ && isGeneratedNode(children.item(i + 1), methods)) {
+ nodesToDelete.add(node);
+ }
+ }
+
+ for (Node node : nodesToDelete) {
+ existingRootElement.removeChild(node);
+ }
+
+ // add the new generated elements
+ children = newRootElement.getChildNodes();
+ length = children.getLength();
+ Node firstChild = existingRootElement.getFirstChild();
+ for (int i = 0; i < length; i++) {
+ Node node = children.item(i);
+ // don't add the last node if it is only white space
+ if (i == length - 1 && isWhiteSpace(node)) {
+ break;
+ }
+
+ Node newNode = existingDocument.importNode(node, true);
+ if (firstChild == null) {
+ existingRootElement.appendChild(newNode);
+ } else {
+ existingRootElement.insertBefore(newNode, firstChild);
+ }
+ }
+
+ // pretty print the result
+ return prettyPrint(existingDocument);
+ }
+
+ private static String prettyPrint(Document document) throws ShellException {
+ DomWriter dw = new DomWriter();
+ String s = dw.toString(document);
+ return s;
+ }
+
+ private static boolean isGeneratedNode(Node node, List methods) {
+ boolean rc = false;
+
+ if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) node;
+ String id = element.getAttribute("id"); //$NON-NLS-1$
+ if (methods.contains(id)) {
+ return true;
+ }
+ if (id != null) {
+ for (String prefix : MergeConstants.OLD_XML_ELEMENT_PREFIXES) {
+ if (id.startsWith(prefix)) {
+ rc = true;
+ break;
+ }
+ }
+ }
+
+ if (rc == false) {
+ // check for new node format - if the first non-whitespace node
+ // is an XML comment, and the comment includes
+ // one of the old element tags,
+ // then it is a generated node
+ NodeList children = node.getChildNodes();
+ int length = children.getLength();
+ for (int i = 0; i < length; i++) {
+ Node childNode = children.item(i);
+ if (isWhiteSpace(childNode)) {
+ continue;
+ } else if (childNode.getNodeType() == Node.COMMENT_NODE) {
+ Comment comment = (Comment) childNode;
+ String commentData = comment.getData();
+ for (String tag : MergeConstants.OLD_ELEMENT_TAGS) {
+ if (commentData.contains(tag)) {
+ rc = true;
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ return rc;
+ }
+
+ private static boolean isWhiteSpace(Node node) {
+ boolean rc = false;
+
+ if (node != null && node.getNodeType() == Node.TEXT_NODE) {
+ Text tn = (Text) node;
+ if (tn.getData().trim().length() == 0) {
+ rc = true;
+ }
+ }
+
+ return rc;
+ }
+}
\ No newline at end of file