├── lib ├── ojdbc14.jar ├── sqljdbc4-4.0.jar ├── sqlite-jdbc-3.19.3.jar ├── postgresql-9.4.1209.jar ├── javaparser-core-3.6.25.jar ├── gene-plugin-1.0-SNAPSHOT.jar ├── mariadb-java-client-2.3.0.jar ├── mybatis-generator-core-1.3.7.jar ├── mysql-connector-java-5.1.38.jar └── mysql-connector-java-8.0.11.jar ├── .gitignore ├── screenshots ├── 20181206172726.png ├── 20181206172740.png ├── 20181206172825.png └── 20181206172856.png ├── src └── com │ └── github │ └── leecho │ └── idea │ └── plugin │ └── mybatis │ └── generator │ ├── contants │ └── PluginContants.java │ ├── ui │ ├── GenerateSettingTabUI.java │ ├── ColumnSettingUI.form │ ├── DatabaseCredentialUI.java │ ├── ColumnSettingUI.java │ ├── ColumnTablePanel.java │ ├── GeneratorSettingUI.java │ └── GenerateSettingUI.java │ ├── model │ ├── Credential.java │ ├── DbType.java │ ├── ColumnSetting.java │ ├── ColumnSettingModel.java │ ├── TableInfo.java │ ├── AbstractTableModel.java │ ├── GlobalConfig.java │ └── TableConfig.java │ ├── plugin │ ├── RenameExampleClassPlugin.java │ ├── SwaggerPlugin.java │ └── LombokPlugin.java │ ├── generate │ ├── GenerateCallback.java │ ├── MergeableShellCallback.java │ ├── MyBatisCodeGenerator.java │ └── MyBatisGenerateCommand.java │ ├── util │ ├── StringUtils.java │ ├── JTextFieldHintListener.java │ ├── DatabaseUtils.java │ ├── JavaFileMerger.java │ └── XmlFileMerger.java │ ├── action │ └── MainAction.java │ └── setting │ ├── SettingConfigurable.java │ └── MyBatisGeneratorConfiguration.java ├── README.md ├── mybatis-generator-plus.iml └── resources └── META-INF └── plugin.xml /lib/ojdbc14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/ojdbc14.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea 3 | out 4 | *.iml 5 | 6 | *.idea -------------------------------------------------------------------------------- /lib/sqljdbc4-4.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/sqljdbc4-4.0.jar -------------------------------------------------------------------------------- /lib/sqlite-jdbc-3.19.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/sqlite-jdbc-3.19.3.jar -------------------------------------------------------------------------------- /lib/postgresql-9.4.1209.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/postgresql-9.4.1209.jar -------------------------------------------------------------------------------- /lib/javaparser-core-3.6.25.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/javaparser-core-3.6.25.jar -------------------------------------------------------------------------------- /screenshots/20181206172726.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/screenshots/20181206172726.png -------------------------------------------------------------------------------- /screenshots/20181206172740.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/screenshots/20181206172740.png -------------------------------------------------------------------------------- /screenshots/20181206172825.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/screenshots/20181206172825.png -------------------------------------------------------------------------------- /screenshots/20181206172856.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/screenshots/20181206172856.png -------------------------------------------------------------------------------- /lib/gene-plugin-1.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/gene-plugin-1.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /lib/mariadb-java-client-2.3.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/mariadb-java-client-2.3.0.jar -------------------------------------------------------------------------------- /lib/mybatis-generator-core-1.3.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/mybatis-generator-core-1.3.7.jar -------------------------------------------------------------------------------- /lib/mysql-connector-java-5.1.38.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/mysql-connector-java-5.1.38.jar -------------------------------------------------------------------------------- /lib/mysql-connector-java-8.0.11.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leecho/mybatis-generator-plus/HEAD/lib/mysql-connector-java-8.0.11.jar -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/contants/PluginContants.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.contants; 2 | 3 | public class PluginContants { 4 | public static final String PLUGIN_NAME = "mybatis-generator"; 5 | } 6 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/ui/GenerateSettingTabUI.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.ui; 2 | 3 | import com.intellij.ide.ui.laf.darcula.ui.DarculaTabbedPaneUI; 4 | import com.intellij.util.ui.JBUI; 5 | 6 | /** 7 | * @author LIQIU 8 | * created on 2019/6/20 9 | **/ 10 | public class GenerateSettingTabUI extends DarculaTabbedPaneUI { 11 | 12 | @Override 13 | public void installDefaults(){ 14 | super.installDefaults(); 15 | this.tabInsets = JBUI.insets(5,30); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/Credential.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | /** 4 | * 保存数据库连接对应的用户名,密码存在keepass库中 5 | * Created by kangtian on 2018/8/3. 6 | */ 7 | public class Credential { 8 | 9 | //用户名 10 | private String username; 11 | 12 | 13 | public Credential() { 14 | } 15 | 16 | public Credential(String username) { 17 | this.username = username; 18 | 19 | } 20 | 21 | 22 | 23 | public String getUsername() { 24 | return username; 25 | } 26 | 27 | public void setUsername(String username) { 28 | this.username = username; 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyBatis Generator Plus 2 | 一款与Idea无缝集成的好用的MyBatis生成器 3 | ## 特性: 4 | - 与Idea DataSource插件集成,操作方便 5 | - 提供UI界面对Java代码路径,XML文件路径进行配置 6 | - 提供增强选项,可以选择分页、Lombok等功能 7 | - 支持合并Mapper文件和Xml文件,可以放心修改原来的Mapper文件,无需担心被覆盖 8 | 9 | ## 操作手册 10 | - 在idea中建立数据库 11 | - 选中要生成的表右键点击弹出菜单,选择 "Generator Mybatis Code" 12 | ![avatar](screenshots/20181206172856.png) 13 | 14 | - 在弹出的界面中进行生成配置: 15 | ![avatar](screenshots/20181206172726.png) 16 | 17 | - 首次生成需要配置数据库密码: 18 | ![avatar](screenshots/20181206172740.png) 19 | 20 | - 配置好之后点击OK生成代码,生成后右下角弹出提示,可以点击文件快速预览 21 | ![avatar](screenshots/20181206172825.png) 22 | 23 | ## 如何安装 24 | [点击这里](https://github.com/leecho/mybatis-generator-plus/releases)下载安装包进行安装 25 | 26 | ## 感谢 27 | 本项目是在[better-mybatis-generator](https://github.com/kmaster/better-mybatis-generator)基础之上进行开发的 -------------------------------------------------------------------------------- /mybatis-generator-plus.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/plugin/RenameExampleClassPlugin.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.plugin; 2 | 3 | import org.mybatis.generator.api.IntrospectedTable; 4 | import org.mybatis.generator.api.PluginAdapter; 5 | 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; 11 | import static org.mybatis.generator.internal.util.messages.Messages.getString; 12 | 13 | public class RenameExampleClassPlugin extends PluginAdapter { 14 | private String target; 15 | 16 | /** 17 | * 18 | */ 19 | public RenameExampleClassPlugin() { 20 | } 21 | 22 | @Override 23 | public boolean validate(List warnings) { 24 | 25 | target = this.getProperties().getProperty("target"); 26 | boolean valid = stringHasValue(target); 27 | 28 | if (!valid) { 29 | if (!stringHasValue(target)) { 30 | warnings.add(getString("ValidationError.18", 31 | "RenameExampleClassPlugin", 32 | "searchString")); 33 | } 34 | } 35 | 36 | return valid; 37 | } 38 | 39 | @Override 40 | public void initialized(IntrospectedTable introspectedTable) { 41 | introspectedTable.setExampleType(target); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/generate/GenerateCallback.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.generate; 2 | 3 | import com.intellij.openapi.progress.ProgressIndicator; 4 | import com.intellij.openapi.ui.popup.Balloon; 5 | import org.mybatis.generator.api.ProgressCallback; 6 | 7 | public class GenerateCallback implements ProgressCallback { 8 | 9 | private ProgressIndicator indicator; 10 | 11 | private Balloon balloon; 12 | 13 | public GenerateCallback(ProgressIndicator indicator, Balloon balloon) { 14 | this.indicator = indicator; 15 | this.balloon = balloon; 16 | } 17 | 18 | @Override 19 | public void introspectionStarted(int i) { 20 | } 21 | 22 | @Override 23 | public void generationStarted(int i) { 24 | } 25 | 26 | @Override 27 | public void saveStarted(int i) { 28 | } 29 | 30 | @Override 31 | public void startTask(String s) { 32 | System.out.println("Start Task: " + s); 33 | indicator.setText(s); 34 | indicator.setFraction(indicator.getFraction() + 0.1); 35 | } 36 | 37 | @Override 38 | public void done() { 39 | indicator.setText("Generate Finished"); 40 | indicator.setFraction(1); 41 | this.balloon.hide(); 42 | } 43 | 44 | @Override 45 | public void checkCancel() throws InterruptedException { 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.util; 2 | 3 | /** 4 | * Created by Owen on 6/18/16. 5 | */ 6 | public class StringUtils { 7 | 8 | /** 9 | * 10 | * convert string from slash style to camel style, such as my_course will convert to MyCourse 11 | * 12 | * @param str 13 | * @return 14 | */ 15 | public static String dbStringToCamelStyle(String str) { 16 | if (str != null) { 17 | str = str.toLowerCase(); 18 | StringBuilder sb = new StringBuilder(); 19 | sb.append(String.valueOf(str.charAt(0)).toUpperCase()); 20 | for (int i = 1; i < str.length(); i++) { 21 | char c = str.charAt(i); 22 | if (c != '_') { 23 | sb.append(c); 24 | } else { 25 | if (i + 1 < str.length()) { 26 | sb.append(String.valueOf(str.charAt(i + 1)).toUpperCase()); 27 | i++; 28 | } 29 | } 30 | } 31 | return sb.toString(); 32 | } 33 | return null; 34 | } 35 | public static boolean isEmpty(Object str) { 36 | return str == null || "".equals(str); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/generate/MergeableShellCallback.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.generate; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.util.JavaFileMerger; 4 | import org.mybatis.generator.exception.ShellException; 5 | import org.mybatis.generator.internal.DefaultShellCallback; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | 10 | /** 11 | * @author LIQIU 12 | */ 13 | public class MergeableShellCallback extends DefaultShellCallback { 14 | 15 | public MergeableShellCallback(boolean overwrite) { 16 | super(overwrite); 17 | } 18 | 19 | @Override 20 | public boolean isMergeSupported() { 21 | return true; 22 | } 23 | 24 | @Override 25 | public String mergeJavaFile(String newFileSource, File existingFile, String[] javadocTags, String fileEncoding) throws ShellException { 26 | String filePath = existingFile.getAbsolutePath().replace(".java", ""); 27 | if (filePath.endsWith("Mapper")) { 28 | try { 29 | return new JavaFileMerger().getNewJavaFile(newFileSource, existingFile.getAbsolutePath()); 30 | } catch (FileNotFoundException e) { 31 | throw new ShellException(e); 32 | } 33 | } else { 34 | return newFileSource; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/util/JTextFieldHintListener.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.util; 2 | import javax.swing.*; 3 | import java.awt.*; 4 | import java.awt.event.FocusEvent; 5 | import java.awt.event.FocusListener; 6 | /** 7 | * 输入框提示 8 | * Created by kangtian on 2018/8/3. 9 | */ 10 | public class JTextFieldHintListener implements FocusListener { 11 | private String hintText; 12 | private JTextField textField; 13 | public JTextFieldHintListener(JTextField jTextField,String hintText) { 14 | this.textField = jTextField; 15 | this.hintText = hintText; 16 | //默认直接显示 17 | jTextField.setText(hintText); 18 | jTextField.setForeground(Color.GRAY); 19 | } 20 | 21 | @Override 22 | public void focusGained(FocusEvent e) { 23 | //获取焦点时,清空提示内容 24 | String temp = textField.getText(); 25 | if(temp.equals(hintText)) { 26 | textField.setText(""); 27 | textField.setForeground(Color.BLACK); 28 | } 29 | 30 | } 31 | 32 | @Override 33 | public void focusLost(FocusEvent e) { 34 | //失去焦点时,没有输入内容,显示提示内容 35 | String temp = textField.getText(); 36 | if(temp.equals("")) { 37 | textField.setForeground(Color.GRAY); 38 | textField.setText(hintText); 39 | } 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/util/DatabaseUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.util; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.model.DbType; 4 | 5 | import java.sql.Connection; 6 | import java.sql.DriverManager; 7 | import java.sql.SQLException; 8 | 9 | public class DatabaseUtils { 10 | 11 | public static void testConnection(String driverClass, String url, String username, String password, boolean isMySQL8) throws ClassNotFoundException, SQLException { 12 | boolean connected = false; 13 | Connection conn = null; 14 | if (driverClass.contains("oracle")) { 15 | Class.forName(DbType.Oracle.getDriverClass()); 16 | } else if (driverClass.contains("mysql")) { 17 | if (!isMySQL8) { 18 | Class.forName(DbType.MySQL.getDriverClass()); 19 | } else { 20 | Class.forName(DbType.MySQL_8.getDriverClass()); 21 | url += "?serverTimezone=UTC"; 22 | } 23 | } else if (driverClass.contains("postgresql")) { 24 | Class.forName(DbType.PostgreSQL.getDriverClass()); 25 | } else if (driverClass.contains("sqlserver")) { 26 | Class.forName(DbType.SqlServer.getDriverClass()); 27 | } else if (driverClass.contains("sqlite")) { 28 | Class.forName(DbType.Sqlite.getDriverClass()); 29 | } else if (driverClass.contains("mariadb")) { 30 | Class.forName(DbType.MariaDB.getDriverClass()); 31 | } 32 | 33 | try { 34 | conn = DriverManager.getConnection(url, username, password); 35 | } finally { 36 | if (conn != null) { 37 | try { 38 | conn.close(); 39 | } catch (SQLException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/DbType.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | public enum DbType { 4 | 5 | MySQL("com.mysql.jdbc.Driver", "jdbc:mysql://%s:%s/%s?useUnicode=true&useSSL=false&characterEncoding=%s", "mysql-connector-java-5.1.38.jar"), 6 | MySQL_8("com.mysql.cj.jdbc.Driver", "jdbc:mysql://%s:%s/%s?serverTimezone=UTC&useUnicode=true&useSSL=false&characterEncoding=%s", "mysql-connector-java-8.0.11.jar"), 7 | Oracle("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@%s:%s:%s", "ojdbc14.jar"), 8 | PostgreSQL("org.postgresql.Driver", "jdbc:postgresql://%s:%s/%s", "postgresql-9.4.1209.jar"), 9 | SqlServer("com.microsoft.sqlserver.jdbc.SQLServerDriver", "jdbc:sqlserver://%s:%s;databaseName=%s", "sqljdbc4-4.0.jar"), 10 | Sqlite("org.sqlite.JDBC", "jdbc:sqlite:%s", "sqlite-jdbc-3.19.3.jar"), 11 | MariaDB("org.mariadb.jdbc.Driver", "", "mariadb-java-client-2.3.0.jar"); 12 | 13 | private final String driverClass; 14 | private final String connectionUrlPattern; 15 | private final String connectorJarFile; 16 | 17 | DbType(String driverClass, String connectionUrlPattern, String connectorJarFile) { 18 | this.driverClass = driverClass; 19 | this.connectionUrlPattern = connectionUrlPattern; 20 | this.connectorJarFile = connectorJarFile; 21 | } 22 | 23 | public String getDriverClass() { 24 | return driverClass; 25 | } 26 | 27 | public String getConnectionUrlPattern() { 28 | return connectionUrlPattern; 29 | } 30 | 31 | public String getConnectorJarFile() { 32 | return connectorJarFile; 33 | } 34 | } -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/action/MainAction.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.action; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.ui.GenerateSettingUI; 4 | import com.intellij.database.psi.DbTable; 5 | import com.intellij.openapi.actionSystem.AnAction; 6 | import com.intellij.openapi.actionSystem.AnActionEvent; 7 | import com.intellij.openapi.actionSystem.LangDataKeys; 8 | import com.intellij.openapi.ui.Messages; 9 | import com.intellij.psi.PsiElement; 10 | 11 | /** 12 | * Mybatis Generator Plus工具生成类 13 | * Created by kangtian on 2018/7/17. 14 | */ 15 | public class MainAction extends AnAction { 16 | 17 | 18 | /** 19 | * 点击后打开插件主页面 20 | * 21 | * @param e 22 | */ 23 | @Override 24 | public void actionPerformed(AnActionEvent e) { 25 | PsiElement[] psiElements = e.getData(LangDataKeys.PSI_ELEMENT_ARRAY); 26 | if (psiElements == null || psiElements.length == 0) { 27 | Messages.showMessageDialog("Please select one or more tables", "Mybatis Generator Plus", Messages.getWarningIcon()); 28 | return; 29 | } 30 | if (psiElements.length > 1) { 31 | Messages.showMessageDialog("Please select only one table", "Mybatis Generator Plus", Messages.getWarningIcon()); 32 | return; 33 | } 34 | for (PsiElement psiElement : psiElements) { 35 | if (!(psiElement instanceof DbTable)) { 36 | Messages.showMessageDialog("Please select one or more tables", "Mybatis Generator Plus", Messages.getWarningIcon()); 37 | return; 38 | } 39 | } 40 | GenerateSettingUI ui = new GenerateSettingUI(e); 41 | ui.show(); 42 | /*if (ui.showAndGet()) { 43 | ui.generate(); 44 | }*/ 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/ui/ColumnSettingUI.form: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/ColumnSetting.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | /** 4 | * 类型隐射信息 5 | * 6 | * @author makejava 7 | * @version 1.0.0 8 | * @since 2018/07/17 13:10 9 | */ 10 | public class ColumnSetting { 11 | /** 12 | * 列类型 13 | */ 14 | private String column; 15 | /** 16 | * java类型 17 | */ 18 | private String javaType; 19 | 20 | private String jdbcType; 21 | 22 | private String javaProperty; 23 | 24 | private Boolean ignore; 25 | 26 | private Boolean changed; 27 | 28 | private String comment; 29 | 30 | public ColumnSetting(){ 31 | 32 | } 33 | 34 | public String getColumn() { 35 | return column; 36 | } 37 | 38 | public void setColumn(String column) { 39 | this.column = column; 40 | } 41 | 42 | public String getJavaType() { 43 | return javaType; 44 | } 45 | 46 | public void setJavaType(String javaType) { 47 | this.javaType = javaType; 48 | } 49 | 50 | public String getJdbcType() { 51 | return jdbcType; 52 | } 53 | 54 | public void setJdbcType(String jdbcType) { 55 | this.jdbcType = jdbcType; 56 | } 57 | 58 | public String getJavaProperty() { 59 | return javaProperty; 60 | } 61 | 62 | public void setJavaProperty(String javaProperty) { 63 | this.javaProperty = javaProperty; 64 | } 65 | 66 | public Boolean getChanged() { 67 | return changed; 68 | } 69 | 70 | public void setChanged(Boolean changed) { 71 | this.changed = changed; 72 | } 73 | 74 | public Boolean getIgnore() { 75 | return ignore; 76 | } 77 | 78 | public void setIgnore(Boolean ignore) { 79 | this.ignore = ignore; 80 | } 81 | 82 | public String getComment() { 83 | return comment; 84 | } 85 | 86 | public void setComment(String comment) { 87 | this.comment = comment; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/ColumnSettingModel.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | 4 | import com.intellij.openapi.ui.Messages; 5 | 6 | /** 7 | * 类型隐射模型 8 | * 9 | * @author makejava 10 | * @version 1.0.0 11 | * @since 2018/07/17 13:10 12 | */ 13 | public class ColumnSettingModel extends AbstractTableModel { 14 | @Override 15 | protected String[] initColumnName() { 16 | return new String[]{"Column", "Jdbc Type", "Java Property", "Java Type", "Ignore", "Comment"}; 17 | } 18 | 19 | @Override 20 | protected Object[] toObj(ColumnSetting entity) { 21 | return new Object[]{entity.getColumn(), entity.getJdbcType(), entity.getJavaProperty(), entity.getJavaType(), entity.getIgnore(), entity.getComment()}; 22 | } 23 | 24 | @Override 25 | protected boolean setVal(ColumnSetting setting, int columnIndex, Object val) { 26 | if (val == null || String.valueOf(val).length() == 0 || String.valueOf(val).equals("")) { 27 | Messages.showMessageDialog("The value must not be null", "Mybatis Generator Plus", Messages.getWarningIcon()); 28 | return false; 29 | } 30 | if (columnIndex == 0) { 31 | setting.setColumn((String) val); 32 | } else if (columnIndex == 1) { 33 | if (setting.getJdbcType().equals(val)) { 34 | return false; 35 | } 36 | setting.setJdbcType((String) val); 37 | } else if (columnIndex == 2) { 38 | if (setting.getJavaProperty().equals(val)) { 39 | return false; 40 | } 41 | setting.setJavaProperty((String) val); 42 | } else if (columnIndex == 3) { 43 | if (setting.getJavaType().equals(val)) { 44 | return false; 45 | } 46 | setting.setJavaType((String) val); 47 | } else if (columnIndex == 4) { 48 | setting.setIgnore((Boolean) val); 49 | } 50 | setting.setChanged(true); 51 | return true; 52 | } 53 | 54 | @Override 55 | public boolean isCellEditable(int row, int column) { 56 | return column != 0 && column != 5; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/setting/SettingConfigurable.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.setting; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.ui.GeneratorSettingUI; 4 | import com.intellij.openapi.options.ConfigurationException; 5 | import com.intellij.openapi.options.SearchableConfigurable; 6 | import com.intellij.openapi.project.Project; 7 | import com.sun.istack.internal.NotNull; 8 | import org.jetbrains.annotations.Nls; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import javax.swing.*; 12 | 13 | /** 14 | *配置设置界面 15 | * Created by kangtian on 2018/7/18. 16 | */ 17 | public class SettingConfigurable implements SearchableConfigurable { 18 | private GeneratorSettingUI mainPanel; 19 | 20 | @SuppressWarnings("FieldCanBeLocal") 21 | private final Project project; 22 | 23 | 24 | public SettingConfigurable(@NotNull Project project) { 25 | this.project = project; 26 | } 27 | 28 | @Nls 29 | @Override 30 | public String getDisplayName() { 31 | return "Mybatis Generator Plus Plus"; 32 | } 33 | 34 | @Nullable 35 | @Override 36 | public String getHelpTopic() { 37 | return "gene.helpTopic"; 38 | } 39 | 40 | @NotNull 41 | @Override 42 | public String getId() { 43 | return "Mybatis.Generator.Plugin"; 44 | } 45 | 46 | @Nullable 47 | @Override 48 | public Runnable enableSearch(String s) { 49 | return null; 50 | } 51 | 52 | @Nullable 53 | @Override 54 | public JComponent createComponent() { 55 | mainPanel = new GeneratorSettingUI(); 56 | mainPanel.createUI(project); 57 | return mainPanel.getContentPane(); 58 | } 59 | 60 | @Override 61 | public boolean isModified() { 62 | return mainPanel.isModified(); 63 | } 64 | 65 | @Override 66 | public void apply() { 67 | mainPanel.apply(); 68 | } 69 | 70 | @Override 71 | public void reset() { 72 | mainPanel.reset(); 73 | } 74 | 75 | @Override 76 | public void disposeUIResources() { 77 | mainPanel = null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/TableInfo.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | import com.intellij.database.model.DasColumn; 4 | import com.intellij.database.psi.DbTable; 5 | import com.intellij.database.util.DasUtil; 6 | import com.intellij.util.containers.JBIterable; 7 | 8 | import java.util.*; 9 | 10 | public class TableInfo { 11 | 12 | public final DbTable tableElement; 13 | 14 | private List columns; 15 | 16 | private List primaryKeys = new ArrayList(); 17 | 18 | 19 | public TableInfo(DbTable tableElement) { 20 | this.tableElement = tableElement; 21 | List columns = new ArrayList(); 22 | 23 | JBIterable columnsIter = DasUtil.getColumns(tableElement); 24 | List dasColumns = columnsIter.toList(); 25 | for (DasColumn dasColumn : dasColumns) { 26 | columns.add(dasColumn); 27 | 28 | if (DasUtil.isPrimary(dasColumn)) { 29 | primaryKeys.add(dasColumn.getName()); 30 | } 31 | 32 | } 33 | 34 | this.columns = columns; 35 | } 36 | 37 | public String getTableName() { 38 | return tableElement.getName(); 39 | } 40 | 41 | public List getColumns() { 42 | return columns; 43 | } 44 | 45 | public List getColumnsName() { 46 | List columnsName = new ArrayList<>(); 47 | for (DasColumn column : columns) { 48 | columnsName.add(column.getName()); 49 | } 50 | return columnsName; 51 | } 52 | 53 | public List getPrimaryKeys() { 54 | return this.primaryKeys; 55 | } 56 | 57 | public List getNonPrimaryColumns() { 58 | Set pKNameSet = new HashSet(); 59 | for (String pkName : getPrimaryKeys()) { 60 | pKNameSet.add(pkName); 61 | } 62 | 63 | List ret = new ArrayList(); 64 | for (DasColumn column : columns) { 65 | if (!pKNameSet.contains(column.getName())) { 66 | ret.add(column); 67 | } 68 | } 69 | 70 | return ret; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/setting/MyBatisGeneratorConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.setting; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableConfig; 4 | import com.github.leecho.idea.plugin.mybatis.generator.model.Credential; 5 | import com.intellij.openapi.components.PersistentStateComponent; 6 | import com.intellij.openapi.components.ServiceManager; 7 | import com.intellij.openapi.components.State; 8 | import com.intellij.openapi.components.Storage; 9 | import com.intellij.openapi.project.Project; 10 | import com.intellij.util.xmlb.XmlSerializerUtil; 11 | import com.github.leecho.idea.plugin.mybatis.generator.model.GlobalConfig; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | import java.util.Map; 15 | 16 | 17 | /** 18 | * 配置持久化 19 | */ 20 | @State(name = "MyBatisGeneratorConfiguration", storages = {@Storage("mybatis-generator-config.xml")}) 21 | public class MyBatisGeneratorConfiguration implements PersistentStateComponent { 22 | 23 | private GlobalConfig globalConfig; 24 | private Map credentials; 25 | private Map tableConfigs; 26 | 27 | @Nullable 28 | public static MyBatisGeneratorConfiguration getInstance(Project project) { 29 | return ServiceManager.getService(project, MyBatisGeneratorConfiguration.class); 30 | } 31 | 32 | @Override 33 | @Nullable 34 | public MyBatisGeneratorConfiguration getState() { 35 | return this; 36 | } 37 | 38 | @Override 39 | public void loadState(MyBatisGeneratorConfiguration myBatisGeneratorConfiguration) { 40 | XmlSerializerUtil.copyBean(myBatisGeneratorConfiguration, this); 41 | } 42 | 43 | public Map getCredentials() { 44 | return credentials; 45 | } 46 | 47 | public void setCredentials(Map credentials) { 48 | this.credentials = credentials; 49 | } 50 | 51 | public Map getTableConfigs() { 52 | return tableConfigs; 53 | } 54 | 55 | public void setTableConfigs(Map tableConfigs) { 56 | this.tableConfigs = tableConfigs; 57 | } 58 | 59 | public GlobalConfig getGlobalConfig() { 60 | if (this.globalConfig == null) { 61 | return GlobalConfig.getDefault(); 62 | } else { 63 | return globalConfig; 64 | } 65 | } 66 | 67 | public void setGlobalConfig(GlobalConfig globalConfig) { 68 | this.globalConfig = globalConfig; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/util/JavaFileMerger.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.util; 2 | 3 | import com.github.javaparser.JavaParser; 4 | import com.github.javaparser.ast.CompilationUnit; 5 | import com.github.javaparser.ast.ImportDeclaration; 6 | import com.github.javaparser.ast.Node; 7 | import com.github.javaparser.ast.NodeList; 8 | import com.github.javaparser.ast.body.MethodDeclaration; 9 | 10 | import java.io.File; 11 | import java.io.FileNotFoundException; 12 | import java.util.Arrays; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | import java.util.stream.Collectors; 16 | 17 | /** 18 | * @author LIQIU 19 | */ 20 | public class JavaFileMerger { 21 | 22 | public String getNewJavaFile(String newFileSource, String existingFileFullPath) throws FileNotFoundException { 23 | CompilationUnit newCompilationUnit = JavaParser.parse(newFileSource); 24 | CompilationUnit existingCompilationUnit = JavaParser.parse(new File(existingFileFullPath)); 25 | return mergerFile(newCompilationUnit, existingCompilationUnit, newFileSource); 26 | } 27 | 28 | public String mergerFile(CompilationUnit newCompilationUnit, CompilationUnit existingCompilationUnit, String newFileSource) { 29 | 30 | NodeList newsImports = newCompilationUnit.getImports(); 31 | NodeList existsImports = existingCompilationUnit.getImports(); 32 | HashSet allImports = new HashSet<>(); 33 | allImports.addAll(newsImports); 34 | allImports.addAll(existsImports); 35 | allImports.removeAll(newsImports); 36 | 37 | List sources = Arrays.stream(newFileSource.split("\n")).collect(Collectors.toList()); 38 | 39 | sources.addAll(newsImports.size() + 2, allImports.stream().map(importDeclaration -> importDeclaration.toString().replace("\r\n","")).collect(Collectors.toList())); 40 | 41 | 42 | List newMethods = newCompilationUnit.getTypes().get(0).getMethods(); 43 | List oldMethods = existingCompilationUnit.getTypes().get(0).getMethods(); 44 | HashSet allMethods = new HashSet<>(); 45 | allMethods.addAll(newMethods); 46 | allMethods.addAll(oldMethods); 47 | allMethods.removeAll(newMethods); 48 | 49 | sources.addAll(sources.size() - 1, allMethods.stream().map(methodDeclaration -> "\n" + " " + methodDeclaration.toString()).collect(Collectors.toList())); 50 | return String.join("\n", sources); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/AbstractTableModel.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | import javax.swing.table.DefaultTableModel; 4 | import java.util.List; 5 | 6 | /** 7 | * 抽象的表模型 8 | * 9 | * @author makejava 10 | * @version 1.0.0 11 | * @since 2018/07/17 13:10 12 | */ 13 | public abstract class AbstractTableModel extends DefaultTableModel { 14 | /** 15 | * 数据 16 | */ 17 | private List data; 18 | 19 | /** 20 | * 构造方法 21 | */ 22 | public AbstractTableModel() { 23 | for (String columnName : initColumnName()) { 24 | super.addColumn(columnName); 25 | } 26 | } 27 | 28 | /** 29 | * 初始化方法 30 | * 31 | * @param data 数据 32 | */ 33 | public void init(List data) { 34 | if (data.isEmpty()) { 35 | return; 36 | } 37 | // 先移除后赋值,修复复制分组后无数据展示问题 38 | removeAllRow(); 39 | this.data = data; 40 | data.forEach(item -> super.addRow(toObj(item))); 41 | } 42 | 43 | public List getData() { 44 | return this.data; 45 | } 46 | 47 | 48 | /** 49 | * 移除所有行 50 | */ 51 | private void removeAllRow() { 52 | int rowCount = getRowCount(); 53 | if (rowCount > 0) { 54 | for (int i = 0; i < rowCount; i++) { 55 | // 只移除行数据,不移除储存数据,修复切换分组数据自动清空BUG 56 | super.removeRow(0); 57 | } 58 | } 59 | } 60 | 61 | /** 62 | * 移除指定行数据 63 | * 64 | * @param row 行号 65 | */ 66 | @Override 67 | public void removeRow(int row) { 68 | super.removeRow(row); 69 | this.data.remove(row); 70 | } 71 | 72 | /** 73 | * 设置值到指定行指定列 74 | * 75 | * @param aValue 值 76 | * @param row 行号 77 | * @param column 列号 78 | */ 79 | @Override 80 | public void setValueAt(Object aValue, int row, int column) { 81 | T obj = data.get(row); 82 | if (setVal(obj, column, aValue)) { 83 | super.setValueAt(aValue, row, column); 84 | } 85 | } 86 | 87 | /** 88 | * 添加一行数据 89 | * 90 | * @param entity 实体数据 91 | */ 92 | public void addRow(T entity) { 93 | super.addRow(toObj(entity)); 94 | this.data.add(entity); 95 | } 96 | 97 | /** 98 | * 抽象初始化列名 99 | * 100 | * @return 列名 101 | */ 102 | protected abstract String[] initColumnName(); 103 | 104 | /** 105 | * 实体类转数据数组 106 | * 107 | * @param entity 实体类 108 | * @return 数据数组 109 | */ 110 | protected abstract Object[] toObj(T entity); 111 | 112 | /** 113 | * 设置实体类的值 114 | * 115 | * @param obj 实体类 116 | * @param columnIndex 列索引 117 | * @param val 值 118 | */ 119 | protected abstract boolean setVal(T obj, int columnIndex, Object val); 120 | } 121 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/ui/DatabaseCredentialUI.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.ui; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.contants.PluginContants; 4 | import com.github.leecho.idea.plugin.mybatis.generator.model.Credential; 5 | import com.github.leecho.idea.plugin.mybatis.generator.setting.MyBatisGeneratorConfiguration; 6 | import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils; 7 | import com.intellij.openapi.ui.DialogWrapper; 8 | import com.intellij.openapi.ui.VerticalFlowLayout; 9 | import com.intellij.ui.JBColor; 10 | import com.intellij.ui.components.JBPasswordField; 11 | import com.intellij.util.ui.JBUI; 12 | import com.intellij.credentialStore.CredentialAttributes; 13 | import com.intellij.credentialStore.Credentials; 14 | import com.intellij.ide.passwordSafe.PasswordSafe; 15 | import com.intellij.openapi.project.Project; 16 | import com.intellij.openapi.vfs.VirtualFile; 17 | import com.intellij.ui.components.JBPanel; 18 | import com.intellij.ui.components.JBTextField; 19 | import org.jetbrains.annotations.Nullable; 20 | 21 | import javax.swing.*; 22 | import java.awt.*; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | /** 27 | * 账号密码输入界面 28 | * Created by kangtian on 2018/8/3. 29 | */ 30 | public class DatabaseCredentialUI extends DialogWrapper { 31 | 32 | private MyBatisGeneratorConfiguration myBatisGeneratorConfiguration; 33 | private String url; 34 | private Project project; 35 | private JPanel contentPanel = new JBPanel<>(); 36 | 37 | private JTextField usernameField = new JBTextField(30); 38 | private JTextField passwordField = new JBPasswordField(); 39 | private JLabel errorMessage = new JLabel(""); 40 | 41 | 42 | public DatabaseCredentialUI(Project project, String url) throws HeadlessException { 43 | super(project); 44 | this.url = url; 45 | this.project = project; 46 | this.myBatisGeneratorConfiguration = MyBatisGeneratorConfiguration.getInstance(project); 47 | setTitle("Connect to Database"); 48 | pack(); 49 | 50 | contentPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 51 | Map credentials = myBatisGeneratorConfiguration.getCredentials(); 52 | 53 | JPanel usernamePanel = new JBPanel<>(); 54 | usernamePanel.setLayout(new BoxLayout(usernamePanel, BoxLayout.X_AXIS)); 55 | usernamePanel.setBorder(JBUI.Borders.empty(1)); 56 | JLabel usernameLabel = new JLabel("Username:"); 57 | usernameLabel.setPreferredSize(new Dimension(80, 20)); 58 | usernamePanel.add(usernameLabel); 59 | usernamePanel.add(usernameField); 60 | if(credentials != null && credentials.containsKey(url)){ 61 | usernameField.setText(credentials.get(url).getUsername()); 62 | } 63 | 64 | JPanel passwordPanel = new JBPanel<>(); 65 | passwordPanel.setLayout(new BoxLayout(passwordPanel, BoxLayout.X_AXIS)); 66 | passwordPanel.setBorder(JBUI.Borders.empty(1)); 67 | JLabel passwordLabel = new JLabel("Password:"); 68 | passwordLabel.setPreferredSize(new Dimension(80, 20)); 69 | passwordPanel.add(passwordLabel); 70 | passwordPanel.add(passwordField); 71 | contentPanel.add(usernamePanel); 72 | contentPanel.add(passwordPanel); 73 | contentPanel.add(errorMessage); 74 | errorMessage.setForeground(JBColor.RED); 75 | this.init(); 76 | } 77 | 78 | @Override 79 | protected void doOKAction() { 80 | 81 | if (StringUtils.isEmpty(usernameField.getText())) { 82 | errorMessage.setText("Username must not be null"); 83 | return; 84 | } 85 | 86 | if (StringUtils.isEmpty(passwordField.getText())) { 87 | errorMessage.setText("Password must not be null"); 88 | return; 89 | } 90 | 91 | Map credentials = myBatisGeneratorConfiguration.getCredentials(); 92 | if (credentials == null) { 93 | credentials = new HashMap<>(); 94 | } 95 | credentials.put(url, new Credential(usernameField.getText())); 96 | CredentialAttributes attributes = new CredentialAttributes(PluginContants.PLUGIN_NAME + "-" + url, usernameField.getText(), this.getClass(), false); 97 | Credentials saveCredentials = new Credentials(attributes.getUserName(), passwordField.getText()); 98 | PasswordSafe.getInstance().set(attributes, saveCredentials); 99 | myBatisGeneratorConfiguration.setCredentials(credentials); 100 | VirtualFile baseDir = project.getBaseDir(); 101 | baseDir.refresh(false, true); 102 | 103 | super.doOKAction(); 104 | } 105 | 106 | @Nullable 107 | @Override 108 | protected JComponent createCenterPanel() { 109 | return this.contentPanel; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/ui/ColumnSettingUI.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.ui; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableConfig; 4 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableInfo; 5 | import com.github.leecho.idea.plugin.mybatis.generator.model.ColumnSetting; 6 | import com.github.leecho.idea.plugin.mybatis.generator.model.ColumnSettingModel; 7 | import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils; 8 | import com.intellij.openapi.project.Project; 9 | import com.intellij.openapi.ui.DialogWrapper; 10 | import org.jdesktop.swingx.JXTable; 11 | import org.jetbrains.annotations.Nullable; 12 | import org.mybatis.generator.api.IntrospectedColumn; 13 | import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl; 14 | import org.mybatis.generator.internal.types.JdbcTypeNameTranslator; 15 | 16 | import javax.swing.*; 17 | import java.awt.*; 18 | import java.sql.Types; 19 | import java.util.ArrayList; 20 | 21 | /** 22 | * 类型映射设置 23 | * 24 | * @author makejava 25 | * @version 1.0.0 26 | * @since 2018/07/17 13:10 27 | */ 28 | public class ColumnSettingUI extends DialogWrapper { 29 | /** 30 | * 主面板 31 | */ 32 | private JPanel mainPanel; 33 | /** 34 | * 类型映射表 35 | */ 36 | private JTable columnSettingTable; 37 | 38 | /** 39 | * 类型映射表模型 40 | */ 41 | private ColumnSettingModel columnSettingModel; 42 | 43 | private TableConfig tableConfig; 44 | 45 | public ColumnSettingUI(Project project, TableConfig tableConfig, TableInfo tableInfo) { 46 | super(project); 47 | //添加类型 48 | // 初始化操作 49 | this.tableConfig = tableConfig; 50 | load(tableConfig, tableInfo); 51 | columnSettingTable.getColumnModel().setColumnMargin(3); 52 | columnSettingTable.getColumnModel().getColumn(4).setCellEditor(new JXTable.BooleanEditor()); 53 | columnSettingTable.getColumnModel().getColumn(3).setWidth(50); 54 | this.setTitle("Column Setting"); 55 | mainPanel.setPreferredSize(new Dimension(800,300)); 56 | this.init(); 57 | } 58 | 59 | @Nullable 60 | @Override 61 | protected JComponent createCenterPanel() { 62 | return mainPanel; 63 | } 64 | 65 | @Override 66 | protected void doOKAction() { 67 | java.util.List columnSettingList = this.columnSettingModel.getData(); 68 | columnSettingList.forEach(columnSetting -> { 69 | if (columnSetting.getChanged()) { 70 | columnSetting.setChanged(false); 71 | tableConfig.getColumnSettings().put(columnSetting.getColumn(), columnSetting); 72 | } 73 | }); 74 | super.doOKAction(); 75 | } 76 | 77 | /** 78 | * 初始化方法 79 | */ 80 | protected void load(TableConfig tableConfig, TableInfo tableInfo) { 81 | //初始化表格 82 | this.columnSettingModel = new ColumnSettingModel(); 83 | JavaTypeResolverDefaultImpl resolver = new JavaTypeResolverDefaultImpl(); 84 | java.util.List columnSettingList = new ArrayList<>(); 85 | tableInfo.getColumns().forEach(dasColumn -> { 86 | 87 | ColumnSetting columnSetting = tableConfig.getColumnSettings().get(dasColumn.getName()); 88 | IntrospectedColumn introspectedColumn = new IntrospectedColumn(); 89 | String typeName = dasColumn.getDataType().typeName.toUpperCase(); 90 | if ("DATETIME".equals(typeName)) { 91 | introspectedColumn.setJdbcType(Types.TIMESTAMP); 92 | } else if ("INT".equals(typeName)) { 93 | introspectedColumn.setJdbcType(Types.INTEGER); 94 | } else { 95 | introspectedColumn.setJdbcType(JdbcTypeNameTranslator.getJdbcType(typeName)); 96 | } 97 | introspectedColumn.setLength(dasColumn.getDataType().getLength()); 98 | introspectedColumn.setScale(dasColumn.getDataType().getScale()); 99 | 100 | if (columnSetting == null) { 101 | columnSetting = new ColumnSetting(); 102 | columnSetting.setColumn(dasColumn.getName()); 103 | String property = StringUtils.dbStringToCamelStyle(dasColumn.getName()); 104 | property = property.substring(0, 1).toLowerCase() + property.substring(1); 105 | columnSetting.setJavaProperty(property); 106 | columnSetting.setJdbcType(resolver.calculateJdbcTypeName(introspectedColumn)); 107 | columnSetting.setJavaType(resolver.calculateJavaType(introspectedColumn).getShortName()); 108 | columnSetting.setIgnore(false); 109 | }else{ 110 | if(!columnSetting.getJdbcType().equals(resolver.calculateJdbcTypeName(introspectedColumn))){ 111 | columnSetting.setJdbcType(resolver.calculateJdbcTypeName(introspectedColumn)); 112 | columnSetting.setJavaType(resolver.calculateJavaType(introspectedColumn).getShortName()); 113 | } 114 | } 115 | columnSetting.setComment(dasColumn.getComment()); 116 | columnSetting.setChanged(false); 117 | columnSettingList.add(columnSetting); 118 | }); 119 | columnSettingModel.init(columnSettingList); 120 | this.columnSettingTable.setModel(columnSettingModel); 121 | } 122 | 123 | } -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/plugin/SwaggerPlugin.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.plugin; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils; 4 | import org.mybatis.generator.api.IntrospectedColumn; 5 | import org.mybatis.generator.api.IntrospectedTable; 6 | import org.mybatis.generator.api.PluginAdapter; 7 | import org.mybatis.generator.api.dom.java.Field; 8 | import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; 9 | import org.mybatis.generator.api.dom.java.Interface; 10 | import org.mybatis.generator.api.dom.java.TopLevelClass; 11 | 12 | import java.util.List; 13 | 14 | 15 | /** 16 | * A MyBatis Generator plugin to use Lombok's annotations. 17 | * For example, use @Data annotation instead of getter ands setter. 18 | * 19 | * @author Paolo Predonzani (http://softwareloop.com/) 20 | */ 21 | public class SwaggerPlugin extends PluginAdapter { 22 | 23 | /** 24 | * @param warnings list of warnings 25 | * @return always true 26 | */ 27 | @Override 28 | public boolean validate(List warnings) { 29 | return true; 30 | } 31 | 32 | /** 33 | * Intercepts base record class generation 34 | * 35 | * @param topLevelClass the generated base record class 36 | * @param introspectedTable The class containing information about the table as 37 | * introspected from the database 38 | * @return always true 39 | */ 40 | @Override 41 | public boolean modelBaseRecordClassGenerated( 42 | TopLevelClass topLevelClass, 43 | IntrospectedTable introspectedTable 44 | ) { 45 | addAnnotations(topLevelClass, introspectedTable.getRemarks()); 46 | return true; 47 | } 48 | 49 | /** 50 | * Intercepts primary key class generation 51 | * 52 | * @param topLevelClass the generated primary key class 53 | * @param introspectedTable The class containing information about the table as 54 | * introspected from the database 55 | * @return always true 56 | */ 57 | @Override 58 | public boolean modelPrimaryKeyClassGenerated( 59 | TopLevelClass topLevelClass, 60 | IntrospectedTable introspectedTable 61 | ) { 62 | addAnnotations(topLevelClass, introspectedTable.getRemarks()); 63 | return true; 64 | } 65 | 66 | /** 67 | * Intercepts "record with blob" class generation 68 | * 69 | * @param topLevelClass the generated record with BLOBs class 70 | * @param introspectedTable The class containing information about the table as 71 | * introspected from the database 72 | * @return always true 73 | */ 74 | @Override 75 | public boolean modelRecordWithBLOBsClassGenerated( 76 | TopLevelClass topLevelClass, 77 | IntrospectedTable introspectedTable 78 | ) { 79 | addAnnotations(topLevelClass, introspectedTable.getRemarks()); 80 | return true; 81 | } 82 | 83 | @Override 84 | public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { 85 | if (!StringUtils.isEmpty(introspectedColumn.getRemarks())) { 86 | addFieldAnnotations(topLevelClass, field, introspectedColumn.getRemarks()); 87 | } 88 | return true; 89 | } 90 | 91 | /** 92 | * Adds the lombok annotations' imports and annotations to the class 93 | * 94 | * @param topLevelClass the partially implemented model class 95 | */ 96 | private void addFieldAnnotations(TopLevelClass topLevelClass, Field field, String name) { 97 | topLevelClass.addImportedType(new FullyQualifiedJavaType("io.swagger.annotations.ApiModelProperty")); 98 | field.addAnnotation(String.format("@ApiModelProperty(\"%s\")", name)); 99 | } 100 | 101 | /** 102 | * Adds the lombok annotations' imports and annotations to the class 103 | * 104 | * @param topLevelClass the partially implemented model class 105 | */ 106 | private void addAnnotations(TopLevelClass topLevelClass, String name) { 107 | topLevelClass.addImportedType(new FullyQualifiedJavaType("io.swagger.annotations.ApiModel")); 108 | String[] parts = name.split("\\."); 109 | topLevelClass.addAnnotation(String.format("@ApiModel(\"%s\")", parts[parts.length - 1])); 110 | } 111 | 112 | 113 | @Override 114 | public boolean clientGenerated( 115 | Interface interfaze, 116 | TopLevelClass topLevelClass, 117 | IntrospectedTable introspectedTable 118 | ) { 119 | interfaze.addImportedType(new FullyQualifiedJavaType( 120 | "org.apache.ibatis.annotations.Mapper")); 121 | interfaze.addAnnotation("@Mapper"); 122 | return true; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | com.github.leecho.idea.plugin.mybatis.generator 3 | MyBatis Generator Plus 4 | 1.5 5 | Leecho 6 | 7 | 8 | 10 |
  • 11 | Integrate with the Idea Database tool
    12 | Support mapper class file merge
    13 | Support mapper xml file merge
    14 | Support customize postfix for mapper class
    15 | Support customize postfix for example class
    16 | Support table prefix for domain class
    17 | Support customize setting for column
    18 | Support for IDEA the latest version.
    19 | Optimize Mysql8 database connection.
    20 | Add MariaDB support 21 |
  • 22 | 23 | ]]> 24 | 26 |
  • 27 | 集成Idea Database工具
    28 | 支持Mapper类文件自动合并
    29 | 支持Mapper XML文件自动合并
    30 | 支持自动忽略表前缀
    31 | 支持自定义Mapper类后缀
    32 | 支持自定义Example类后缀
    33 | 支持修改字段数据类型
    34 | 支持忽略字段
    35 |
  • 36 | 37 | ]]> 38 | 40 |
  • Use in idea database tool,right click table to generate mybatis files (include:mapper、example、domain、xml).Currently supported databases: Mysql, Oracle. To be verified: Mysql 8, Postgre SQL and SQL Server
  • 41 |
  • Step1: Connecting to Your Database: View > Tool Windows > Database.
  • 42 |
  • Step2: Select one tablesRight Click and select Generate MyBatis Code to open generator main UI.
  • 43 |
  • Step3: Check configuration in main ui,click ok.
  • 44 |
  • Step4: Provide account and password for the first time.
  • 45 |
  • Step5: Generate work finish,check files and it can be use.
  • 46 |
  • Setting: Tools > MyBatis Generator Plus set custom default configuration,If not, use the program default configuration.
  • 47 |
  • More tutorial please visit here
  • 48 | 49 | 50 |
      51 |
    • 在idea的database工具中使用,右击选择表生成mybatis相关的代码。目前已支持的数据库:Mysql、Mysql8(可能需要设置数据库时区time_zone = '+8:00')、Oracle、MariaDB。待验证:PostgreSQL与SQL Server
    • 52 |
    • Step1: 连接Database: View > Tool Windows > Database
    • 53 |
    • Step2: 选择表,右击选择功能 Generate MyBatis Code 打开主页面。
    • 54 |
    • Step3: 检查配置无误后点击 ok
    • 55 |
    • Step4: 首次使用时请提供账号密码。p
    • 56 |
    • Step5: 生成完成,检查、使用代码。
    • 57 |
    • Setting: Tools > MyBatis Generator Plus 此处设置默认配置,未设置则使用程序默认配置。
    • 58 |
    59 | ]]> 60 | 61 |
    62 | 63 | 64 | 66 |
  • v1.0
    67 | Init Version 68 |
  • 69 |
  • v1.1
    70 | Update description 71 |
  • 72 |
  • v1.2
    73 | add comment column for column setting ui
    74 | fix database column type change bug 75 |
  • 76 |
  • v1.3
    77 | optimization some feature 78 |
  • 79 |
  • v1.4
    80 | add swagger support options
    81 | add table prefix support
    82 | new ui for generate setting
    83 | fixed some bugs
    84 |
  • 85 |
  • v1.5
    86 | fix cannot get table remark bug
    87 | fix cannot support sql server bug
    88 | add progressbar for display connect to database
    89 |
    90 |
  • 91 | 92 | ]]> 93 |
    94 | 95 | 96 | 97 | com.intellij.database 98 | 99 | 102 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 |
    -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/ui/ColumnTablePanel.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @author LIQIU 4 | * created on 2019/6/20 5 | **/ 6 | package com.github.leecho.idea.plugin.mybatis.generator.ui; 7 | 8 | import com.github.leecho.idea.plugin.mybatis.generator.model.ColumnSetting; 9 | import com.github.leecho.idea.plugin.mybatis.generator.model.ColumnSettingModel; 10 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableConfig; 11 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableInfo; 12 | import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils; 13 | import com.intellij.openapi.ui.VerticalFlowLayout; 14 | import com.intellij.ui.components.JBPanel; 15 | import com.intellij.ui.components.JBScrollPane; 16 | import com.intellij.ui.table.JBTable; 17 | import com.intellij.util.ui.JBUI; 18 | import org.jdesktop.swingx.JXTable; 19 | import org.mybatis.generator.api.IntrospectedColumn; 20 | import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl; 21 | import org.mybatis.generator.internal.types.JdbcTypeNameTranslator; 22 | 23 | import javax.swing.*; 24 | import javax.swing.event.TableModelEvent; 25 | import javax.swing.event.TableModelListener; 26 | import java.awt.*; 27 | import java.sql.Types; 28 | import java.util.ArrayList; 29 | 30 | /** 31 | * @author LIQIU 32 | * created on 2019/6/20 33 | **/ 34 | public class ColumnTablePanel extends JBPanel { 35 | 36 | /** 37 | * 类型映射表 38 | */ 39 | private JTable columnSettingTable = new JBTable(); 40 | 41 | /** 42 | * 类型映射表模型 43 | */ 44 | private ColumnSettingModel columnSettingModel; 45 | 46 | private TableConfig tableConfig; 47 | 48 | public ColumnTablePanel(TableConfig tableConfig, TableInfo tableInfo) { 49 | //添加类型 50 | // 初始化操作 51 | this.tableConfig = tableConfig; 52 | load(tableConfig, tableInfo); 53 | this.setName("Columns"); 54 | columnSettingTable.getColumnModel().setColumnMargin(3); 55 | columnSettingTable.getColumnModel().getColumn(4).setCellEditor(new JXTable.BooleanEditor()); 56 | columnSettingTable.getColumnModel().getColumn(3).setWidth(50); 57 | VerticalFlowLayout layout= new VerticalFlowLayout(VerticalFlowLayout.TOP); 58 | layout.setVgap(0); 59 | layout.setHgap(0); 60 | layout.setHorizontalFill(true); 61 | layout.setVerticalFill(true); 62 | this.setLayout(layout); 63 | JBScrollPane jScrollPane = new JBScrollPane(columnSettingTable); 64 | jScrollPane.setPreferredSize(new Dimension(800,320)); 65 | this.setBorder(JBUI.Borders.empty(-11)); 66 | this.add(jScrollPane); 67 | this.setVisible(true); 68 | } 69 | 70 | 71 | /** 72 | * 初始化方法 73 | */ 74 | protected void load(TableConfig tableConfig, TableInfo tableInfo) { 75 | //初始化表格 76 | this.columnSettingModel = new ColumnSettingModel(); 77 | JavaTypeResolverDefaultImpl resolver = new JavaTypeResolverDefaultImpl(); 78 | java.util.List columnSettingList = new ArrayList<>(); 79 | tableInfo.getColumns().forEach(dasColumn -> { 80 | 81 | ColumnSetting columnSetting = tableConfig.getColumnSettings().get(dasColumn.getName()); 82 | IntrospectedColumn introspectedColumn = new IntrospectedColumn(); 83 | String typeName = dasColumn.getDataType().typeName.toUpperCase(); 84 | if ("DATETIME".equals(typeName)) { 85 | introspectedColumn.setJdbcType(Types.TIMESTAMP); 86 | } else if ("INT".equals(typeName)) { 87 | introspectedColumn.setJdbcType(Types.INTEGER); 88 | } else { 89 | introspectedColumn.setJdbcType(JdbcTypeNameTranslator.getJdbcType(typeName)); 90 | } 91 | introspectedColumn.setLength(dasColumn.getDataType().getLength()); 92 | introspectedColumn.setScale(dasColumn.getDataType().getScale()); 93 | 94 | if (columnSetting == null) { 95 | columnSetting = new ColumnSetting(); 96 | columnSetting.setColumn(dasColumn.getName()); 97 | String property = StringUtils.dbStringToCamelStyle(dasColumn.getName()); 98 | property = property.substring(0, 1).toLowerCase() + property.substring(1); 99 | columnSetting.setJavaProperty(property); 100 | columnSetting.setJdbcType(resolver.calculateJdbcTypeName(introspectedColumn)); 101 | columnSetting.setJavaType(resolver.calculateJavaType(introspectedColumn).getShortName()); 102 | columnSetting.setIgnore(false); 103 | } else { 104 | if (!columnSetting.getJdbcType().equals(resolver.calculateJdbcTypeName(introspectedColumn))) { 105 | columnSetting.setJdbcType(resolver.calculateJdbcTypeName(introspectedColumn)); 106 | columnSetting.setJavaType(resolver.calculateJavaType(introspectedColumn).getShortName()); 107 | } 108 | } 109 | columnSetting.setComment(dasColumn.getComment()); 110 | columnSetting.setChanged(false); 111 | columnSettingList.add(columnSetting); 112 | }); 113 | columnSettingModel.init(columnSettingList); 114 | columnSettingModel.addTableModelListener(e -> { 115 | ColumnSetting columnSetting = columnSettingModel.getData().get(e.getFirstRow()); 116 | columnSetting.setChanged(false); 117 | tableConfig.getColumnSettings().put(columnSetting.getColumn(),columnSetting); 118 | }); 119 | this.columnSettingTable.setModel(columnSettingModel); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/GlobalConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | public class GlobalConfig { 4 | 5 | private String moduleRootPath; 6 | private String sourcePath; 7 | private String resourcePath; 8 | private String mapperPostfix; 9 | private String examplePostfix; 10 | 11 | private String domainPackage; 12 | private String mapperPackage; 13 | private String examplePackage; 14 | private String xmlPackage; 15 | 16 | private String tablePrefix; 17 | 18 | /** 19 | * 是否分页 20 | */ 21 | private boolean offsetLimit; 22 | 23 | /** 24 | * 是否生成实体注释(来自表) 25 | */ 26 | private boolean comment; 27 | 28 | /** 29 | * 是否覆盖原xml 30 | */ 31 | private boolean override; 32 | 33 | /** 34 | * 是否生成toString/hashCode/equals方法 35 | */ 36 | private boolean needToStringHashcodeEquals; 37 | 38 | /** 39 | * 是否使用Schema前缀 40 | */ 41 | private boolean useSchemaPrefix; 42 | 43 | /** 44 | * 是否select 增加ForUpdate 45 | */ 46 | private boolean needForUpdate; 47 | 48 | /** 49 | * 是否DAO使用 @Repository 注解 50 | */ 51 | private boolean annotationDAO; 52 | 53 | /** 54 | * 是否DAO方法抽出到公共父接口 55 | */ 56 | private boolean useDAOExtendStyle; 57 | 58 | /** 59 | * 是否JSR310: Date and Time API 60 | */ 61 | private boolean jsr310Support; 62 | 63 | /** 64 | * 是否生成JPA注解 65 | */ 66 | private boolean annotation; 67 | 68 | /** 69 | * 是否使用实际的列名 70 | */ 71 | private boolean useActualColumnNames; 72 | 73 | /** 74 | * 是否启用as别名查询 75 | */ 76 | private boolean useTableNameAlias; 77 | 78 | /** 79 | * 是否使用Example 80 | */ 81 | private boolean useExample; 82 | /** 83 | * 是否是mysql8数据库 84 | */ 85 | private boolean mysql8; 86 | 87 | private boolean lombokAnnotation; 88 | 89 | private boolean lombokBuilderAnnotation; 90 | 91 | private boolean swaggerAnnotation; 92 | 93 | public String getSourcePath() { 94 | return sourcePath; 95 | } 96 | 97 | public void setSourcePath(String sourcePath) { 98 | this.sourcePath = sourcePath; 99 | } 100 | 101 | public String getResourcePath() { 102 | return resourcePath; 103 | } 104 | 105 | public void setResourcePath(String resourcePath) { 106 | this.resourcePath = resourcePath; 107 | } 108 | 109 | public String getMapperPostfix() { 110 | return mapperPostfix; 111 | } 112 | 113 | public void setMapperPostfix(String mapperPostfix) { 114 | this.mapperPostfix = mapperPostfix; 115 | } 116 | 117 | public String getDomainPackage() { 118 | return domainPackage; 119 | } 120 | 121 | public void setDomainPackage(String domainPackage) { 122 | this.domainPackage = domainPackage; 123 | } 124 | 125 | public String getMapperPackage() { 126 | return mapperPackage; 127 | } 128 | 129 | public void setMapperPackage(String mapperPackage) { 130 | this.mapperPackage = mapperPackage; 131 | } 132 | 133 | public String getXmlPackage() { 134 | return xmlPackage; 135 | } 136 | 137 | public void setXmlPackage(String xmlPackage) { 138 | this.xmlPackage = xmlPackage; 139 | } 140 | 141 | public boolean isOffsetLimit() { 142 | return offsetLimit; 143 | } 144 | 145 | public void setOffsetLimit(boolean offsetLimit) { 146 | this.offsetLimit = offsetLimit; 147 | } 148 | 149 | public boolean isComment() { 150 | return comment; 151 | } 152 | 153 | public void setComment(boolean comment) { 154 | this.comment = comment; 155 | } 156 | 157 | public boolean isOverride() { 158 | return override; 159 | } 160 | 161 | public void setOverride(boolean override) { 162 | this.override = override; 163 | } 164 | 165 | public boolean isNeedToStringHashcodeEquals() { 166 | return needToStringHashcodeEquals; 167 | } 168 | 169 | public void setNeedToStringHashcodeEquals(boolean needToStringHashcodeEquals) { 170 | this.needToStringHashcodeEquals = needToStringHashcodeEquals; 171 | } 172 | 173 | public boolean isUseSchemaPrefix() { 174 | return useSchemaPrefix; 175 | } 176 | 177 | public void setUseSchemaPrefix(boolean useSchemaPrefix) { 178 | this.useSchemaPrefix = useSchemaPrefix; 179 | } 180 | 181 | public boolean isNeedForUpdate() { 182 | return needForUpdate; 183 | } 184 | 185 | public void setNeedForUpdate(boolean needForUpdate) { 186 | this.needForUpdate = needForUpdate; 187 | } 188 | 189 | public boolean isAnnotationDAO() { 190 | return annotationDAO; 191 | } 192 | 193 | public void setAnnotationDAO(boolean annotationDAO) { 194 | this.annotationDAO = annotationDAO; 195 | } 196 | 197 | public boolean isUseDAOExtendStyle() { 198 | return useDAOExtendStyle; 199 | } 200 | 201 | public void setUseDAOExtendStyle(boolean useDAOExtendStyle) { 202 | this.useDAOExtendStyle = useDAOExtendStyle; 203 | } 204 | 205 | public boolean isJsr310Support() { 206 | return jsr310Support; 207 | } 208 | 209 | public void setJsr310Support(boolean jsr310Support) { 210 | this.jsr310Support = jsr310Support; 211 | } 212 | 213 | public boolean isAnnotation() { 214 | return annotation; 215 | } 216 | 217 | public void setAnnotation(boolean annotation) { 218 | this.annotation = annotation; 219 | } 220 | 221 | public boolean isUseActualColumnNames() { 222 | return useActualColumnNames; 223 | } 224 | 225 | public void setUseActualColumnNames(boolean useActualColumnNames) { 226 | this.useActualColumnNames = useActualColumnNames; 227 | } 228 | 229 | public boolean isUseTableNameAlias() { 230 | return useTableNameAlias; 231 | } 232 | 233 | public void setUseTableNameAlias(boolean useTableNameAlias) { 234 | this.useTableNameAlias = useTableNameAlias; 235 | } 236 | 237 | public boolean isUseExample() { 238 | return useExample; 239 | } 240 | 241 | public void setUseExample(boolean useExample) { 242 | this.useExample = useExample; 243 | } 244 | 245 | public boolean isMysql8() { 246 | return mysql8; 247 | } 248 | 249 | public void setMysql8(boolean mysql8) { 250 | this.mysql8 = mysql8; 251 | } 252 | 253 | public boolean isLombokAnnotation() { 254 | return lombokAnnotation; 255 | } 256 | 257 | public void setLombokAnnotation(boolean lombokAnnotation) { 258 | this.lombokAnnotation = lombokAnnotation; 259 | } 260 | 261 | public boolean isLombokBuilderAnnotation() { 262 | return lombokBuilderAnnotation; 263 | } 264 | 265 | public void setLombokBuilderAnnotation(boolean lombokBuilderAnnotation) { 266 | this.lombokBuilderAnnotation = lombokBuilderAnnotation; 267 | } 268 | 269 | public String getModuleRootPath() { 270 | return moduleRootPath; 271 | } 272 | 273 | public void setModuleRootPath(String moduleRootPath) { 274 | this.moduleRootPath = moduleRootPath; 275 | } 276 | 277 | public String getExamplePostfix() { 278 | return examplePostfix; 279 | } 280 | 281 | public void setExamplePostfix(String examplePostfix) { 282 | this.examplePostfix = examplePostfix; 283 | } 284 | 285 | public String getExamplePackage() { 286 | return examplePackage; 287 | } 288 | 289 | public void setExamplePackage(String examplePackage) { 290 | this.examplePackage = examplePackage; 291 | } 292 | 293 | public boolean isSwaggerAnnotation() { 294 | return swaggerAnnotation; 295 | } 296 | 297 | public void setSwaggerAnnotation(boolean swaggerAnnotation) { 298 | this.swaggerAnnotation = swaggerAnnotation; 299 | } 300 | 301 | public String getTablePrefix() { 302 | return tablePrefix; 303 | } 304 | 305 | public void setTablePrefix(String tablePrefix) { 306 | this.tablePrefix = tablePrefix; 307 | } 308 | 309 | public static GlobalConfig getDefault() { 310 | GlobalConfig globalConfig = new GlobalConfig(); 311 | globalConfig.setSourcePath("src/main/java"); 312 | globalConfig.setResourcePath("src/main/resources"); 313 | globalConfig.setMapperPostfix("Mapper"); 314 | globalConfig.setXmlPackage("mapper"); 315 | globalConfig.setExamplePostfix("Example"); 316 | globalConfig.setUseExample(true); 317 | globalConfig.setComment(true); 318 | return globalConfig; 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/util/XmlFileMerger.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.util; 2 | 3 | import static org.mybatis.generator.internal.util.messages.Messages.getString; 4 | 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.StringReader; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | import javax.xml.parsers.DocumentBuilder; 14 | import javax.xml.parsers.DocumentBuilderFactory; 15 | import javax.xml.parsers.ParserConfigurationException; 16 | 17 | import com.sun.org.apache.xerces.internal.dom.DeferredTextImpl; 18 | import org.mybatis.generator.api.GeneratedXmlFile; 19 | import org.mybatis.generator.config.MergeConstants; 20 | import org.mybatis.generator.exception.ShellException; 21 | import org.mybatis.generator.internal.DomWriter; 22 | import org.w3c.dom.Comment; 23 | import org.w3c.dom.Document; 24 | import org.w3c.dom.DocumentType; 25 | import org.w3c.dom.Element; 26 | import org.w3c.dom.NamedNodeMap; 27 | import org.w3c.dom.Node; 28 | import org.w3c.dom.NodeList; 29 | import org.w3c.dom.Text; 30 | import org.xml.sax.EntityResolver; 31 | import org.xml.sax.InputSource; 32 | import org.xml.sax.SAXException; 33 | 34 | /** 35 | * This class handles the task of merging changes into an existing XML file. 36 | * 37 | * @author Jeff Butler 38 | */ 39 | public class XmlFileMerger { 40 | private static class NullEntityResolver implements EntityResolver { 41 | /** 42 | * returns an empty reader. This is done so that the parser doesn't 43 | * attempt to read a DTD. We don't need that support for the merge and 44 | * it can cause problems on systems that aren't Internet connected. 45 | */ 46 | @Override 47 | public InputSource resolveEntity(String publicId, String systemId) 48 | throws SAXException, IOException { 49 | 50 | StringReader sr = new StringReader(""); //$NON-NLS-1$ 51 | 52 | return new InputSource(sr); 53 | } 54 | } 55 | 56 | /** 57 | * Utility class - no instances allowed 58 | */ 59 | private XmlFileMerger() { 60 | super(); 61 | } 62 | 63 | public static String getMergedSource(GeneratedXmlFile generatedXmlFile, 64 | File existingFile) throws ShellException { 65 | 66 | try { 67 | return getMergedSource(new InputSource(new StringReader(generatedXmlFile.getFormattedContent())), 68 | new InputSource(new InputStreamReader(new FileInputStream(existingFile), "UTF-8")), //$NON-NLS-1$ 69 | existingFile.getName()); 70 | } catch (IOException e) { 71 | throw new ShellException(getString("Warning.13", //$NON-NLS-1$ 72 | existingFile.getName()), e); 73 | } catch (SAXException e) { 74 | throw new ShellException(getString("Warning.13", //$NON-NLS-1$ 75 | existingFile.getName()), e); 76 | } catch (ParserConfigurationException e) { 77 | throw new ShellException(getString("Warning.13", //$NON-NLS-1$ 78 | existingFile.getName()), e); 79 | } 80 | } 81 | 82 | public static String getMergedSource(InputSource newFile, 83 | InputSource existingFile, String existingFileName) throws IOException, SAXException, 84 | ParserConfigurationException, ShellException { 85 | 86 | DocumentBuilderFactory factory = DocumentBuilderFactory 87 | .newInstance(); 88 | factory.setExpandEntityReferences(false); 89 | DocumentBuilder builder = factory.newDocumentBuilder(); 90 | builder.setEntityResolver(new NullEntityResolver()); 91 | 92 | Document existingDocument = builder.parse(existingFile); 93 | Document newDocument = builder.parse(newFile); 94 | 95 | DocumentType newDocType = newDocument.getDoctype(); 96 | DocumentType existingDocType = existingDocument.getDoctype(); 97 | 98 | if (!newDocType.getName().equals(existingDocType.getName())) { 99 | throw new ShellException(getString("Warning.12", //$NON-NLS-1$ 100 | existingFileName)); 101 | } 102 | 103 | Element existingRootElement = existingDocument.getDocumentElement(); 104 | Element newRootElement = newDocument.getDocumentElement(); 105 | 106 | // reconcile the root element attributes - 107 | // take all attributes from the new element and add to the existing 108 | // element 109 | 110 | // remove all attributes from the existing root element 111 | NamedNodeMap attributes = existingRootElement.getAttributes(); 112 | int attributeCount = attributes.getLength(); 113 | for (int i = attributeCount - 1; i >= 0; i--) { 114 | Node node = attributes.item(i); 115 | existingRootElement.removeAttribute(node.getNodeName()); 116 | } 117 | 118 | // add attributes from the new root node to the old root node 119 | attributes = newRootElement.getAttributes(); 120 | attributeCount = attributes.getLength(); 121 | for (int i = 0; i < attributeCount; i++) { 122 | Node node = attributes.item(i); 123 | existingRootElement.setAttribute(node.getNodeName(), node 124 | .getNodeValue()); 125 | } 126 | 127 | NodeList newMethods = newRootElement.getChildNodes(); 128 | List methods = new ArrayList(); 129 | for (int i = 0; i < newMethods.getLength(); i++) { 130 | Node node = newMethods.item(i); 131 | try { 132 | if (node instanceof DeferredTextImpl) { 133 | continue; 134 | } 135 | Element ele = (Element) node; 136 | methods.add(ele.getAttribute("id")); 137 | } catch (Exception e) { 138 | //#text节点转换会异常 139 | continue; 140 | } 141 | if (i == newMethods.getLength() - 1) { 142 | if (isWhiteSpace(node)) { 143 | break; 144 | } 145 | } 146 | } 147 | 148 | // remove the old generated elements and any 149 | // white space before the old nodes 150 | List nodesToDelete = new ArrayList(); 151 | NodeList children = existingRootElement.getChildNodes(); 152 | int length = children.getLength(); 153 | for (int i = 0; i < length; i++) { 154 | Node node = children.item(i); 155 | if (isGeneratedNode(node, methods)) { 156 | nodesToDelete.add(node); 157 | } else if (isWhiteSpace(node) 158 | && isGeneratedNode(children.item(i + 1), methods)) { 159 | nodesToDelete.add(node); 160 | } 161 | } 162 | 163 | for (Node node : nodesToDelete) { 164 | existingRootElement.removeChild(node); 165 | } 166 | 167 | // add the new generated elements 168 | children = newRootElement.getChildNodes(); 169 | length = children.getLength(); 170 | Node firstChild = existingRootElement.getFirstChild(); 171 | for (int i = 0; i < length; i++) { 172 | Node node = children.item(i); 173 | // don't add the last node if it is only white space 174 | if (i == length - 1 && isWhiteSpace(node)) { 175 | break; 176 | } 177 | 178 | Node newNode = existingDocument.importNode(node, true); 179 | if (firstChild == null) { 180 | existingRootElement.appendChild(newNode); 181 | } else { 182 | existingRootElement.insertBefore(newNode, firstChild); 183 | } 184 | } 185 | 186 | // pretty print the result 187 | return prettyPrint(existingDocument); 188 | } 189 | 190 | private static String prettyPrint(Document document) throws ShellException { 191 | DomWriter dw = new DomWriter(); 192 | String s = dw.toString(document); 193 | return s; 194 | } 195 | 196 | private static boolean isGeneratedNode(Node node, List methods) { 197 | boolean rc = false; 198 | 199 | if (node != null && node.getNodeType() == Node.ELEMENT_NODE) { 200 | Element element = (Element) node; 201 | String id = element.getAttribute("id"); //$NON-NLS-1$ 202 | if (methods.contains(id)) { 203 | return true; 204 | } 205 | if (id != null) { 206 | for (String prefix : MergeConstants.OLD_XML_ELEMENT_PREFIXES) { 207 | if (id.startsWith(prefix)) { 208 | rc = true; 209 | break; 210 | } 211 | } 212 | } 213 | 214 | if (rc == false) { 215 | // check for new node format - if the first non-whitespace node 216 | // is an XML comment, and the comment includes 217 | // one of the old element tags, 218 | // then it is a generated node 219 | NodeList children = node.getChildNodes(); 220 | int length = children.getLength(); 221 | for (int i = 0; i < length; i++) { 222 | Node childNode = children.item(i); 223 | if (isWhiteSpace(childNode)) { 224 | continue; 225 | } else if (childNode.getNodeType() == Node.COMMENT_NODE) { 226 | Comment comment = (Comment) childNode; 227 | String commentData = comment.getData(); 228 | for (String tag : MergeConstants.OLD_ELEMENT_TAGS) { 229 | if (commentData.contains(tag)) { 230 | rc = true; 231 | break; 232 | } 233 | } 234 | } else { 235 | break; 236 | } 237 | } 238 | } 239 | } 240 | 241 | return rc; 242 | } 243 | 244 | private static boolean isWhiteSpace(Node node) { 245 | boolean rc = false; 246 | 247 | if (node != null && node.getNodeType() == Node.TEXT_NODE) { 248 | Text tn = (Text) node; 249 | if (tn.getData().trim().length() == 0) { 250 | rc = true; 251 | } 252 | } 253 | 254 | return rc; 255 | } 256 | } -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/model/TableConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.model; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 界面配置 8 | */ 9 | public class TableConfig { 10 | 11 | /** 12 | * 配置名称 13 | */ 14 | private String name; 15 | 16 | /** 17 | * 表名 18 | */ 19 | private String tableName; 20 | 21 | /** 22 | * 主键 23 | */ 24 | private String primaryKey; 25 | 26 | /** 27 | * 实体名 28 | */ 29 | private String domainName; 30 | 31 | /** 32 | * dao名称 33 | */ 34 | private String mapperName; 35 | 36 | /** 37 | * dao名称 38 | */ 39 | private String exampleName; 40 | 41 | /** 42 | * dao后缀 43 | */ 44 | private String mapperPostfix; 45 | 46 | /** 47 | * dao后缀 48 | */ 49 | private String examplePostfix; 50 | 51 | /** 52 | * 工程目录 53 | */ 54 | private String moduleRootPath; 55 | 56 | private String sourcePath; 57 | private String resourcePath; 58 | 59 | private String basePackage; 60 | private String domainPackage; 61 | 62 | private String mapperPackage; 63 | 64 | private String examplePackage; 65 | 66 | private String xmlPackage; 67 | 68 | private Map columnSettings = new HashMap<>(); 69 | /** 70 | * 是否分页 71 | */ 72 | private boolean offsetLimit; 73 | 74 | /** 75 | * 是否生成实体注释(来自表) 76 | */ 77 | private boolean comment; 78 | 79 | /** 80 | * 是否覆盖原xml 81 | */ 82 | private boolean override; 83 | 84 | /** 85 | * 是否生成toString/hashCode/equals方法 86 | */ 87 | private boolean needToStringHashcodeEquals; 88 | 89 | /** 90 | * 是否使用Schema前缀 91 | */ 92 | private boolean useSchemaPrefix; 93 | 94 | /** 95 | * 是否select 增加ForUpdate 96 | */ 97 | private boolean needForUpdate; 98 | 99 | /** 100 | * 是否DAO使用 @Repository 注解 101 | */ 102 | private boolean annotationDAO; 103 | 104 | /** 105 | * 是否DAO方法抽出到公共父接口 106 | */ 107 | private boolean useDAOExtendStyle; 108 | 109 | /** 110 | * 是否JSR310: Date and Time API 111 | */ 112 | private boolean jsr310Support; 113 | 114 | /** 115 | * 是否生成JPA注解 116 | */ 117 | private boolean annotation; 118 | 119 | /** 120 | * 是否使用实际的列名 121 | */ 122 | private boolean useActualColumnNames; 123 | 124 | /** 125 | * 是否启用as别名查询 126 | */ 127 | private boolean useTableNameAlias; 128 | 129 | /** 130 | * 是否使用Example 131 | */ 132 | private boolean useExample; 133 | /** 134 | * 是否是mysql8数据库 135 | */ 136 | private boolean mysql8; 137 | 138 | private boolean lombokAnnotation; 139 | 140 | private boolean lombokBuilderAnnotation; 141 | 142 | private boolean swaggerAnnotation; 143 | 144 | private String encoding; 145 | private String connectorJarPath; 146 | 147 | public boolean isJsr310Support() { 148 | return jsr310Support; 149 | } 150 | 151 | public void setJsr310Support(boolean jsr310Support) { 152 | this.jsr310Support = jsr310Support; 153 | } 154 | 155 | public boolean isUseSchemaPrefix() { 156 | return useSchemaPrefix; 157 | } 158 | 159 | public void setUseSchemaPrefix(boolean useSchemaPrefix) { 160 | this.useSchemaPrefix = useSchemaPrefix; 161 | } 162 | 163 | public boolean isUseExample() { 164 | return useExample; 165 | } 166 | 167 | public void setUseExample(boolean useExample) { 168 | this.useExample = useExample; 169 | } 170 | 171 | public String getName() { 172 | return name; 173 | } 174 | 175 | public void setName(String name) { 176 | this.name = name; 177 | } 178 | 179 | public String getTableName() { 180 | return tableName; 181 | } 182 | 183 | public void setTableName(String tableName) { 184 | this.tableName = tableName; 185 | } 186 | 187 | public String getDomainName() { 188 | return domainName; 189 | } 190 | 191 | public void setDomainName(String domainName) { 192 | this.domainName = domainName; 193 | } 194 | 195 | public String getConnectorJarPath() { 196 | return connectorJarPath; 197 | } 198 | 199 | public void setConnectorJarPath(String connectorJarPath) { 200 | this.connectorJarPath = connectorJarPath; 201 | } 202 | 203 | public String getModuleRootPath() { 204 | return moduleRootPath; 205 | } 206 | 207 | public void setModuleRootPath(String moduleRootPath) { 208 | this.moduleRootPath = moduleRootPath; 209 | } 210 | 211 | public String getDomainPackage() { 212 | return domainPackage; 213 | } 214 | 215 | public void setDomainPackage(String domainPackage) { 216 | this.domainPackage = domainPackage; 217 | } 218 | 219 | 220 | public String getMapperPackage() { 221 | return mapperPackage; 222 | } 223 | 224 | public void setMapperPackage(String mapperPackage) { 225 | this.mapperPackage = mapperPackage; 226 | } 227 | 228 | 229 | public String getXmlPackage() { 230 | return xmlPackage; 231 | } 232 | 233 | public void setXmlPackage(String xmlPackage) { 234 | this.xmlPackage = xmlPackage; 235 | } 236 | 237 | public boolean isOffsetLimit() { 238 | return offsetLimit; 239 | } 240 | 241 | public void setOffsetLimit(boolean offsetLimit) { 242 | this.offsetLimit = offsetLimit; 243 | } 244 | 245 | public boolean isComment() { 246 | return comment; 247 | } 248 | 249 | public void setComment(boolean comment) { 250 | this.comment = comment; 251 | } 252 | 253 | public boolean isNeedToStringHashcodeEquals() { 254 | return needToStringHashcodeEquals; 255 | } 256 | 257 | public void setNeedToStringHashcodeEquals(boolean needToStringHashcodeEquals) { 258 | this.needToStringHashcodeEquals = needToStringHashcodeEquals; 259 | } 260 | 261 | public boolean isNeedForUpdate() { 262 | return needForUpdate; 263 | } 264 | 265 | public void setNeedForUpdate(boolean needForUpdate) { 266 | this.needForUpdate = needForUpdate; 267 | } 268 | 269 | public boolean isAnnotationDAO() { 270 | return annotationDAO; 271 | } 272 | 273 | public void setAnnotationDAO(boolean annotationDAO) { 274 | this.annotationDAO = annotationDAO; 275 | } 276 | 277 | public boolean isAnnotation() { 278 | return annotation; 279 | } 280 | 281 | public void setAnnotation(boolean annotation) { 282 | this.annotation = annotation; 283 | } 284 | 285 | public boolean isUseActualColumnNames() { 286 | return useActualColumnNames; 287 | } 288 | 289 | public void setUseActualColumnNames(boolean useActualColumnNames) { 290 | this.useActualColumnNames = useActualColumnNames; 291 | } 292 | 293 | public String getMapperName() { 294 | return mapperName; 295 | } 296 | 297 | public void setMapperName(String mapperName) { 298 | this.mapperName = mapperName; 299 | } 300 | 301 | public String getPrimaryKey() { 302 | return primaryKey; 303 | } 304 | 305 | public void setPrimaryKey(String primaryKey) { 306 | this.primaryKey = primaryKey; 307 | } 308 | 309 | public String getEncoding() { 310 | return encoding; 311 | } 312 | 313 | public void setEncoding(String encoding) { 314 | this.encoding = encoding; 315 | } 316 | 317 | public boolean getUseTableNameAlias() { 318 | return useTableNameAlias; 319 | } 320 | 321 | public void setUseTableNameAlias(boolean useTableNameAlias) { 322 | this.useTableNameAlias = useTableNameAlias; 323 | } 324 | 325 | public boolean isUseTableNameAlias() { 326 | return useTableNameAlias; 327 | } 328 | 329 | public boolean isOverride() { 330 | return override; 331 | } 332 | 333 | public void setOverride(boolean override) { 334 | this.override = override; 335 | } 336 | 337 | public void setUseDAOExtendStyle(boolean useDAOExtendStyle) { 338 | this.useDAOExtendStyle = useDAOExtendStyle; 339 | } 340 | 341 | public boolean isUseDAOExtendStyle() { 342 | return useDAOExtendStyle; 343 | } 344 | 345 | public String getSourcePath() { 346 | return sourcePath; 347 | } 348 | 349 | public void setSourcePath(String sourcePath) { 350 | this.sourcePath = sourcePath; 351 | } 352 | 353 | public String getResourcePath() { 354 | return resourcePath; 355 | } 356 | 357 | public void setResourcePath(String resourcePath) { 358 | this.resourcePath = resourcePath; 359 | } 360 | 361 | public String getMapperPostfix() { 362 | return mapperPostfix; 363 | } 364 | 365 | public void setMapperPostfix(String mapperPostfix) { 366 | this.mapperPostfix = mapperPostfix; 367 | } 368 | 369 | public boolean isMysql8() { 370 | return mysql8; 371 | } 372 | 373 | public void setMysql8(boolean mysql8) { 374 | this.mysql8 = mysql8; 375 | } 376 | 377 | public boolean isLombokAnnotation() { 378 | return lombokAnnotation; 379 | } 380 | 381 | public void setLombokAnnotation(boolean lombokAnnotation) { 382 | this.lombokAnnotation = lombokAnnotation; 383 | } 384 | 385 | public boolean isLombokBuilderAnnotation() { 386 | return lombokBuilderAnnotation; 387 | } 388 | 389 | public void setLombokBuilderAnnotation(boolean lombokBuilderAnnotation) { 390 | this.lombokBuilderAnnotation = lombokBuilderAnnotation; 391 | } 392 | 393 | public boolean isSwaggerAnnotation() { 394 | return swaggerAnnotation; 395 | } 396 | 397 | public void setSwaggerAnnotation(boolean swaggerAnnotation) { 398 | this.swaggerAnnotation = swaggerAnnotation; 399 | } 400 | 401 | public String getExamplePackage() { 402 | return examplePackage; 403 | } 404 | 405 | public void setExamplePackage(String examplePackage) { 406 | this.examplePackage = examplePackage; 407 | } 408 | 409 | public String getExamplePostfix() { 410 | return examplePostfix; 411 | } 412 | 413 | public void setExamplePostfix(String examplePostfix) { 414 | this.examplePostfix = examplePostfix; 415 | } 416 | 417 | public String getExampleName() { 418 | return exampleName; 419 | } 420 | 421 | public void setExampleName(String exampleName) { 422 | this.exampleName = exampleName; 423 | } 424 | 425 | public String getBasePackage() { 426 | return basePackage; 427 | } 428 | 429 | public void setBasePackage(String basePackage) { 430 | this.basePackage = basePackage; 431 | } 432 | 433 | public Map getColumnSettings() { 434 | return columnSettings; 435 | } 436 | 437 | public void setColumnSettings(Map columnSettings) { 438 | this.columnSettings = columnSettings; 439 | } 440 | } 441 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/plugin/LombokPlugin.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.plugin; 2 | 3 | import org.mybatis.generator.api.IntrospectedColumn; 4 | import org.mybatis.generator.api.IntrospectedTable; 5 | import org.mybatis.generator.api.PluginAdapter; 6 | import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; 7 | import org.mybatis.generator.api.dom.java.Interface; 8 | import org.mybatis.generator.api.dom.java.Method; 9 | import org.mybatis.generator.api.dom.java.TopLevelClass; 10 | 11 | import java.util.*; 12 | 13 | 14 | /** 15 | * A MyBatis Generator plugin to use Lombok's annotations. 16 | * For example, use @Data annotation instead of getter ands setter. 17 | * 18 | * @author Paolo Predonzani (http://softwareloop.com/) 19 | */ 20 | public class LombokPlugin extends PluginAdapter { 21 | 22 | private final Collection annotations; 23 | 24 | /** 25 | * LombokPlugin constructor 26 | */ 27 | public LombokPlugin() { 28 | annotations = new LinkedHashSet(Annotations.values().length); 29 | } 30 | 31 | /** 32 | * @param warnings list of warnings 33 | * @return always true 34 | */ 35 | @Override 36 | public boolean validate(List warnings) { 37 | return true; 38 | } 39 | 40 | /** 41 | * Intercepts base record class generation 42 | * 43 | * @param topLevelClass the generated base record class 44 | * @param introspectedTable The class containing information about the table as 45 | * introspected from the database 46 | * @return always true 47 | */ 48 | @Override 49 | public boolean modelBaseRecordClassGenerated( 50 | TopLevelClass topLevelClass, 51 | IntrospectedTable introspectedTable 52 | ) { 53 | addAnnotations(topLevelClass); 54 | return true; 55 | } 56 | 57 | /** 58 | * Intercepts primary key class generation 59 | * 60 | * @param topLevelClass the generated primary key class 61 | * @param introspectedTable The class containing information about the table as 62 | * introspected from the database 63 | * @return always true 64 | */ 65 | @Override 66 | public boolean modelPrimaryKeyClassGenerated( 67 | TopLevelClass topLevelClass, 68 | IntrospectedTable introspectedTable 69 | ) { 70 | addAnnotations(topLevelClass); 71 | return true; 72 | } 73 | 74 | /** 75 | * Intercepts "record with blob" class generation 76 | * 77 | * @param topLevelClass the generated record with BLOBs class 78 | * @param introspectedTable The class containing information about the table as 79 | * introspected from the database 80 | * @return always true 81 | */ 82 | @Override 83 | public boolean modelRecordWithBLOBsClassGenerated( 84 | TopLevelClass topLevelClass, 85 | IntrospectedTable introspectedTable 86 | ) { 87 | addAnnotations(topLevelClass); 88 | return true; 89 | } 90 | 91 | /** 92 | * Prevents all getters from being generated. 93 | * See SimpleModelGenerator 94 | * 95 | * @param method the getter, or accessor, method generated for the specified 96 | * column 97 | * @param topLevelClass the partially implemented model class 98 | * @param introspectedColumn The class containing information about the column related 99 | * to this field as introspected from the database 100 | * @param introspectedTable The class containing information about the table as 101 | * introspected from the database 102 | * @param modelClassType the type of class that the field is generated for 103 | */ 104 | @Override 105 | public boolean modelGetterMethodGenerated( 106 | Method method, 107 | TopLevelClass topLevelClass, 108 | IntrospectedColumn introspectedColumn, 109 | IntrospectedTable introspectedTable, 110 | ModelClassType modelClassType 111 | ) { 112 | return false; 113 | } 114 | 115 | /** 116 | * Prevents all setters from being generated 117 | * See SimpleModelGenerator 118 | * 119 | * @param method the setter, or mutator, method generated for the specified 120 | * column 121 | * @param topLevelClass the partially implemented model class 122 | * @param introspectedColumn The class containing information about the column related 123 | * to this field as introspected from the database 124 | * @param introspectedTable The class containing information about the table as 125 | * introspected from the database 126 | * @param modelClassType the type of class that the field is generated for 127 | * @return always false 128 | */ 129 | @Override 130 | public boolean modelSetterMethodGenerated( 131 | Method method, 132 | TopLevelClass topLevelClass, 133 | IntrospectedColumn introspectedColumn, 134 | IntrospectedTable introspectedTable, 135 | ModelClassType modelClassType 136 | ) { 137 | return false; 138 | } 139 | 140 | /** 141 | * Adds the lombok annotations' imports and annotations to the class 142 | * 143 | * @param topLevelClass the partially implemented model class 144 | */ 145 | private void addAnnotations(TopLevelClass topLevelClass) { 146 | for (Annotations annotation : annotations) { 147 | topLevelClass.addImportedType(annotation.javaType); 148 | topLevelClass.addAnnotation(annotation.asAnnotation()); 149 | } 150 | } 151 | 152 | @Override 153 | public void setProperties(Properties properties) { 154 | super.setProperties(properties); 155 | 156 | //@Data is default annotation 157 | annotations.add(Annotations.DATA); 158 | 159 | for (String annotationName : properties.stringPropertyNames()) { 160 | if (annotationName.contains(".")) { 161 | // Not an annotation name 162 | continue; 163 | } 164 | String value = properties.getProperty(annotationName); 165 | if (!Boolean.parseBoolean(value)) { 166 | // The annotation is disabled, skip it 167 | continue; 168 | } 169 | Annotations annotation = Annotations.getValueOf(annotationName); 170 | if (annotation == null) { 171 | continue; 172 | } 173 | String optionsPrefix = annotationName + "."; 174 | for (String propertyName : properties.stringPropertyNames()) { 175 | if (!propertyName.startsWith(optionsPrefix)) { 176 | // A property not related to this annotation 177 | continue; 178 | } 179 | String propertyValue = properties.getProperty(propertyName); 180 | annotation.appendOptions(propertyName, propertyValue); 181 | } 182 | annotations.add(annotation); 183 | annotations.addAll(Annotations.getDependencies(annotation)); 184 | } 185 | } 186 | 187 | @Override 188 | public boolean clientGenerated( 189 | Interface interfaze, 190 | TopLevelClass topLevelClass, 191 | IntrospectedTable introspectedTable 192 | ) { 193 | interfaze.addImportedType(new FullyQualifiedJavaType( 194 | "org.apache.ibatis.annotations.Mapper")); 195 | interfaze.addAnnotation("@Mapper"); 196 | return true; 197 | } 198 | 199 | private enum Annotations { 200 | /** 201 | * 202 | */ 203 | DATA("data", "@Data", "lombok.Data"), 204 | BUILDER("builder", "@Builder", "lombok.Builder"), 205 | ALL_ARGS_CONSTRUCTOR("allArgsConstructor", "@AllArgsConstructor", "lombok.AllArgsConstructor"), 206 | NO_ARGS_CONSTRUCTOR("noArgsConstructor", "@NoArgsConstructor", "lombok.NoArgsConstructor"), 207 | ACCESSORS("accessors", "@Accessors", "lombok.experimental.Accessors"), 208 | TO_STRING("toString", "@ToString", "lombok.ToString"); 209 | 210 | 211 | private final String paramName; 212 | private final String name; 213 | private final FullyQualifiedJavaType javaType; 214 | private final List options; 215 | 216 | 217 | Annotations(String paramName, String name, String className) { 218 | this.paramName = paramName; 219 | this.name = name; 220 | this.javaType = new FullyQualifiedJavaType(className); 221 | this.options = new ArrayList(); 222 | } 223 | 224 | private static Annotations getValueOf(String paramName) { 225 | for (Annotations annotation : Annotations.values()) 226 | if (String.CASE_INSENSITIVE_ORDER.compare(paramName, annotation.paramName) == 0) 227 | return annotation; 228 | 229 | return null; 230 | } 231 | 232 | private static Collection getDependencies(Annotations annotation) { 233 | if (annotation == ALL_ARGS_CONSTRUCTOR) 234 | return Collections.singleton(NO_ARGS_CONSTRUCTOR); 235 | else 236 | return Collections.emptyList(); 237 | } 238 | 239 | // A trivial quoting. 240 | // Because Lombok annotation options type is almost String or boolean. 241 | private static String quote(String value) { 242 | if (Boolean.TRUE.toString().equals(value) || Boolean.FALSE.toString().equals(value)) 243 | // case of boolean, not passed as an array. 244 | return value; 245 | return value.replaceAll("[\\w]+", "\"$0\""); 246 | } 247 | 248 | private void appendOptions(String key, String value) { 249 | String keyPart = key.substring(key.indexOf(".") + 1); 250 | String valuePart = value.contains(",") ? String.format("{%s}", value) : value; 251 | this.options.add(String.format("%s=%s", keyPart, quote(valuePart))); 252 | } 253 | 254 | private String asAnnotation() { 255 | if (options.isEmpty()) { 256 | return name; 257 | } 258 | StringBuilder sb = new StringBuilder(); 259 | sb.append(name); 260 | sb.append("("); 261 | boolean first = true; 262 | for (String option : options) { 263 | if (first) { 264 | first = false; 265 | } else { 266 | sb.append(", "); 267 | } 268 | sb.append(option); 269 | } 270 | sb.append(")"); 271 | return sb.toString(); 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisCodeGenerator.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.generate; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.util.XmlFileMerger; 4 | import org.mybatis.generator.api.GeneratedJavaFile; 5 | import org.mybatis.generator.api.GeneratedXmlFile; 6 | import org.mybatis.generator.api.ProgressCallback; 7 | import org.mybatis.generator.api.ShellCallback; 8 | import org.mybatis.generator.codegen.RootClassInfo; 9 | import org.mybatis.generator.config.Configuration; 10 | import org.mybatis.generator.config.Context; 11 | import org.mybatis.generator.config.MergeConstants; 12 | import org.mybatis.generator.exception.InvalidConfigurationException; 13 | import org.mybatis.generator.exception.ShellException; 14 | import org.mybatis.generator.internal.DefaultShellCallback; 15 | import org.mybatis.generator.internal.NullProgressCallback; 16 | import org.mybatis.generator.internal.ObjectFactory; 17 | 18 | import java.io.*; 19 | import java.sql.SQLException; 20 | import java.util.ArrayList; 21 | import java.util.HashSet; 22 | import java.util.List; 23 | import java.util.Set; 24 | 25 | import static org.mybatis.generator.internal.util.ClassloaderUtility.getCustomClassloader; 26 | import static org.mybatis.generator.internal.util.messages.Messages.getString; 27 | 28 | /** 29 | * This class is the main interface to MyBatis generator. A typical execution of the tool involves these steps: 30 | * 31 | *
      32 | *
    1. Create a Configuration object. The Configuration can be the result of a parsing the XML configuration file, or it 33 | * can be created solely in Java.
    2. 34 | *
    3. Create a MyBatisCodeGenerator object
    4. 35 | *
    5. Call one of the generate() methods
    6. 36 | *
    37 | * 38 | * @author Jeff Butler 39 | * @see org.mybatis.generator.config.xml.ConfigurationParser 40 | */ 41 | public class MyBatisCodeGenerator { 42 | 43 | /** 44 | * The configuration. 45 | */ 46 | private Configuration configuration; 47 | 48 | /** 49 | * The shell callback. 50 | */ 51 | private ShellCallback shellCallback; 52 | 53 | /** 54 | * The generated java files. 55 | */ 56 | private List generatedJavaFiles; 57 | 58 | /** 59 | * The generated xml files. 60 | */ 61 | private List generatedXmlFiles; 62 | 63 | /** 64 | * The warnings. 65 | */ 66 | private List warnings; 67 | 68 | /** 69 | * The projects. 70 | */ 71 | private Set projects; 72 | 73 | /** 74 | * Constructs a MyBatisCodeGenerator object. 75 | * 76 | * @param configuration The configuration for this invocation 77 | * @param shellCallback an instance of a ShellCallback interface. You may specify 78 | * null in which case the DefaultShellCallback will 79 | * be used. 80 | * @param warnings Any warnings generated during execution will be added to this 81 | * list. Warnings do not affect the running of the tool, but they 82 | * may affect the results. A typical warning is an unsupported 83 | * data type. In that case, the column will be ignored and 84 | * generation will continue. You may specify null if 85 | * you do not want warnings returned. 86 | * @throws InvalidConfigurationException if the specified configuration is invalid 87 | */ 88 | public MyBatisCodeGenerator(Configuration configuration, ShellCallback shellCallback, 89 | List warnings) throws InvalidConfigurationException { 90 | super(); 91 | if (configuration == null) { 92 | throw new IllegalArgumentException(getString("RuntimeError.2")); //$NON-NLS-1$ 93 | } else { 94 | this.configuration = configuration; 95 | } 96 | 97 | if (shellCallback == null) { 98 | this.shellCallback = new DefaultShellCallback(false); 99 | } else { 100 | this.shellCallback = shellCallback; 101 | } 102 | 103 | if (warnings == null) { 104 | this.warnings = new ArrayList(); 105 | } else { 106 | this.warnings = warnings; 107 | } 108 | generatedJavaFiles = new ArrayList(); 109 | generatedXmlFiles = new ArrayList(); 110 | projects = new HashSet(); 111 | 112 | this.configuration.validate(); 113 | } 114 | 115 | /** 116 | * This is the main method for generating code. This method is long running, but progress can be provided and the 117 | * method can be canceled through the ProgressCallback interface. This version of the method runs all configured 118 | * contexts. 119 | * 120 | * @param callback an instance of the ProgressCallback interface, or null if you do not require progress 121 | * information 122 | * @throws SQLException the SQL exception 123 | * @throws IOException Signals that an I/O exception has occurred. 124 | * @throws InterruptedException if the method is canceled through the ProgressCallback 125 | */ 126 | public void generate(ProgressCallback callback) throws SQLException, 127 | IOException, InterruptedException { 128 | generate(callback, null, null, true); 129 | } 130 | 131 | /** 132 | * This is the main method for generating code. This method is long running, but progress can be provided and the 133 | * method can be canceled through the ProgressCallback interface. 134 | * 135 | * @param callback an instance of the ProgressCallback interface, or null if you do not require progress 136 | * information 137 | * @param contextIds a set of Strings containing context ids to run. Only the contexts with an id specified in this list 138 | * will be run. If the list is null or empty, than all contexts are run. 139 | * @throws SQLException the SQL exception 140 | * @throws IOException Signals that an I/O exception has occurred. 141 | * @throws InterruptedException if the method is canceled through the ProgressCallback 142 | */ 143 | public void generate(ProgressCallback callback, Set contextIds) 144 | throws SQLException, IOException, InterruptedException { 145 | generate(callback, contextIds, null, true); 146 | } 147 | 148 | /** 149 | * This is the main method for generating code. This method is long running, but progress can be provided and the 150 | * method can be cancelled through the ProgressCallback interface. 151 | * 152 | * @param callback an instance of the ProgressCallback interface, or null if you do not require progress 153 | * information 154 | * @param contextIds a set of Strings containing context ids to run. Only the contexts with an id specified in this list 155 | * will be run. If the list is null or empty, than all contexts are run. 156 | * @param fullyQualifiedTableNames a set of table names to generate. The elements of the set must be Strings that exactly match what's 157 | * specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully 158 | * qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration 159 | * will be used for code generation. 160 | * @throws SQLException the SQL exception 161 | * @throws IOException Signals that an I/O exception has occurred. 162 | * @throws InterruptedException if the method is canceled through the ProgressCallback 163 | */ 164 | public void generate(ProgressCallback callback, Set contextIds, 165 | Set fullyQualifiedTableNames) throws SQLException, 166 | IOException, InterruptedException { 167 | generate(callback, contextIds, fullyQualifiedTableNames, true); 168 | } 169 | 170 | /** 171 | * This is the main method for generating code. This method is long running, but progress can be provided and the 172 | * method can be cancelled through the ProgressCallback interface. 173 | * 174 | * @param callback an instance of the ProgressCallback interface, or null if you do not require progress 175 | * information 176 | * @param contextIds a set of Strings containing context ids to run. Only the contexts with an id specified in this list 177 | * will be run. If the list is null or empty, than all contexts are run. 178 | * @param fullyQualifiedTableNames a set of table names to generate. The elements of the set must be Strings that exactly match what's 179 | * specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully 180 | * qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration 181 | * will be used for code generation. 182 | * @param writeFiles if true, then the generated files will be written to disk. If false, 183 | * then the generator runs but nothing is written 184 | * @throws SQLException the SQL exception 185 | * @throws IOException Signals that an I/O exception has occurred. 186 | * @throws InterruptedException if the method is canceled through the ProgressCallback 187 | */ 188 | public void generate(ProgressCallback callback, Set contextIds, 189 | Set fullyQualifiedTableNames, boolean writeFiles) throws SQLException, 190 | IOException, InterruptedException { 191 | 192 | if (callback == null) { 193 | callback = new NullProgressCallback(); 194 | } 195 | 196 | generatedJavaFiles.clear(); 197 | generatedXmlFiles.clear(); 198 | ObjectFactory.reset(); 199 | RootClassInfo.reset(); 200 | 201 | // calculate the contexts to run 202 | List contextsToRun; 203 | if (contextIds == null || contextIds.size() == 0) { 204 | contextsToRun = configuration.getContexts(); 205 | } else { 206 | contextsToRun = new ArrayList(); 207 | for (Context context : configuration.getContexts()) { 208 | if (contextIds.contains(context.getId())) { 209 | contextsToRun.add(context); 210 | } 211 | } 212 | } 213 | 214 | // setup custom classloader if required 215 | if (configuration.getClassPathEntries().size() > 0) { 216 | ClassLoader classLoader = getCustomClassloader(configuration.getClassPathEntries()); 217 | ObjectFactory.addExternalClassLoader(classLoader); 218 | } 219 | 220 | // now run the introspections... 221 | int totalSteps = 0; 222 | for (Context context : contextsToRun) { 223 | totalSteps += context.getIntrospectionSteps(); 224 | } 225 | callback.introspectionStarted(totalSteps); 226 | 227 | for (Context context : contextsToRun) { 228 | context.introspectTables(callback, warnings, 229 | fullyQualifiedTableNames); 230 | } 231 | 232 | // now run the generates 233 | totalSteps = 0; 234 | for (Context context : contextsToRun) { 235 | totalSteps += context.getGenerationSteps(); 236 | } 237 | callback.generationStarted(totalSteps); 238 | 239 | for (Context context : contextsToRun) { 240 | context.generateFiles(callback, generatedJavaFiles, 241 | generatedXmlFiles, warnings); 242 | } 243 | 244 | // now save the files 245 | if (writeFiles) { 246 | callback.saveStarted(generatedXmlFiles.size() 247 | + generatedJavaFiles.size()); 248 | 249 | for (GeneratedXmlFile gxf : generatedXmlFiles) { 250 | projects.add(gxf.getTargetProject()); 251 | writeGeneratedXmlFile(gxf, callback); 252 | } 253 | 254 | for (GeneratedJavaFile gjf : generatedJavaFiles) { 255 | projects.add(gjf.getTargetProject()); 256 | writeGeneratedJavaFile(gjf, callback); 257 | } 258 | 259 | for (String project : projects) { 260 | shellCallback.refreshProject(project); 261 | } 262 | } 263 | 264 | callback.done(); 265 | } 266 | 267 | private void writeGeneratedJavaFile(GeneratedJavaFile gjf, ProgressCallback callback) 268 | throws InterruptedException, IOException { 269 | File targetFile; 270 | String source; 271 | try { 272 | File directory = shellCallback.getDirectory(gjf 273 | .getTargetProject(), gjf.getTargetPackage()); 274 | targetFile = new File(directory, gjf.getFileName()); 275 | if (targetFile.exists()) { 276 | if (shellCallback.isMergeSupported()) { 277 | source = shellCallback.mergeJavaFile(gjf .getFormattedContent(), 278 | targetFile, 279 | MergeConstants.OLD_ELEMENT_TAGS, 280 | gjf.getFileEncoding()); 281 | } else if (shellCallback.isOverwriteEnabled()) { 282 | source = gjf.getFormattedContent(); 283 | warnings.add(getString("Warning.11", //$NON-NLS-1$ 284 | targetFile.getAbsolutePath())); 285 | } else { 286 | source = gjf.getFormattedContent(); 287 | targetFile = getUniqueFileName(directory, gjf 288 | .getFileName()); 289 | warnings.add(getString( 290 | "Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$ 291 | } 292 | } else { 293 | source = gjf.getFormattedContent(); 294 | } 295 | 296 | callback.checkCancel(); 297 | callback.startTask(getString( 298 | "Progress.15", targetFile.getName())); //$NON-NLS-1$ 299 | writeFile(targetFile, source, gjf.getFileEncoding()); 300 | } catch (ShellException e) { 301 | warnings.add(e.getMessage()); 302 | } 303 | } 304 | 305 | private void writeGeneratedXmlFile(GeneratedXmlFile gxf, ProgressCallback callback) 306 | throws InterruptedException, IOException { 307 | File targetFile; 308 | String source; 309 | try { 310 | File directory = shellCallback.getDirectory(gxf 311 | .getTargetProject(), gxf.getTargetPackage()); 312 | targetFile = new File(directory, gxf.getFileName()); 313 | if (targetFile.exists()) { 314 | if (gxf.isMergeable()) { 315 | source = XmlFileMerger.getMergedSource(gxf, 316 | targetFile); 317 | } else if (shellCallback.isOverwriteEnabled()) { 318 | source = gxf.getFormattedContent(); 319 | warnings.add(getString("Warning.11", //$NON-NLS-1$ 320 | targetFile.getAbsolutePath())); 321 | } else { 322 | source = gxf.getFormattedContent(); 323 | targetFile = getUniqueFileName(directory, gxf 324 | .getFileName()); 325 | warnings.add(getString( 326 | "Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$ 327 | } 328 | } else { 329 | source = gxf.getFormattedContent(); 330 | } 331 | 332 | callback.checkCancel(); 333 | callback.startTask(getString( 334 | "Progress.15", targetFile.getName())); //$NON-NLS-1$ 335 | writeFile(targetFile, source, "UTF-8"); //$NON-NLS-1$ 336 | } catch (ShellException e) { 337 | warnings.add(e.getMessage()); 338 | } 339 | } 340 | 341 | /** 342 | * Writes, or overwrites, the contents of the specified file. 343 | * 344 | * @param file the file 345 | * @param content the content 346 | * @param fileEncoding the file encoding 347 | * @throws IOException Signals that an I/O exception has occurred. 348 | */ 349 | private void writeFile(File file, String content, String fileEncoding) throws IOException { 350 | FileOutputStream fos = new FileOutputStream(file, false); 351 | OutputStreamWriter osw; 352 | if (fileEncoding == null) { 353 | osw = new OutputStreamWriter(fos); 354 | } else { 355 | osw = new OutputStreamWriter(fos, fileEncoding); 356 | } 357 | 358 | BufferedWriter bw = new BufferedWriter(osw); 359 | bw.write(content); 360 | bw.close(); 361 | } 362 | 363 | /** 364 | * Gets the unique file name. 365 | * 366 | * @param directory the directory 367 | * @param fileName the file name 368 | * @return the unique file name 369 | */ 370 | private File getUniqueFileName(File directory, String fileName) { 371 | File answer = null; 372 | 373 | // try up to 1000 times to generate a unique file name 374 | StringBuilder sb = new StringBuilder(); 375 | for (int i = 1; i < 1000; i++) { 376 | sb.setLength(0); 377 | sb.append(fileName); 378 | sb.append('.'); 379 | sb.append(i); 380 | 381 | File testFile = new File(directory, sb.toString()); 382 | if (!testFile.exists()) { 383 | answer = testFile; 384 | break; 385 | } 386 | } 387 | 388 | if (answer == null) { 389 | throw new RuntimeException(getString( 390 | "RuntimeError.3", directory.getAbsolutePath())); //$NON-NLS-1$ 391 | } 392 | 393 | return answer; 394 | } 395 | 396 | /** 397 | * Returns the list of generated Java files after a call to one of the generate methods. 398 | * This is useful if you prefer to process the generated files yourself and do not want 399 | * the generator to write them to disk. 400 | * 401 | * @return the list of generated Java files 402 | */ 403 | public List getGeneratedJavaFiles() { 404 | return generatedJavaFiles; 405 | } 406 | 407 | /** 408 | * Returns the list of generated XML files after a call to one of the generate methods. 409 | * This is useful if you prefer to process the generated files yourself and do not want 410 | * the generator to write them to disk. 411 | * 412 | * @return the list of generated XML files 413 | */ 414 | public List getGeneratedXmlFiles() { 415 | return generatedXmlFiles; 416 | } 417 | } -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/ui/GeneratorSettingUI.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.ui; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.model.GlobalConfig; 4 | import com.github.leecho.idea.plugin.mybatis.generator.setting.MyBatisGeneratorConfiguration; 5 | import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils; 6 | import com.intellij.ide.util.PackageChooserDialog; 7 | import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; 8 | import com.intellij.openapi.project.Project; 9 | import com.intellij.openapi.ui.Messages; 10 | import com.intellij.openapi.ui.TextBrowseFolderListener; 11 | import com.intellij.openapi.ui.TextFieldWithBrowseButton; 12 | import com.intellij.openapi.ui.VerticalFlowLayout; 13 | import com.intellij.psi.PsiPackage; 14 | import com.intellij.ui.EditorTextFieldWithBrowseButton; 15 | import com.intellij.ui.TitledSeparator; 16 | import com.intellij.ui.components.JBLabel; 17 | import com.intellij.ui.components.JBPanel; 18 | 19 | import javax.swing.*; 20 | import java.awt.*; 21 | import java.awt.event.ActionEvent; 22 | 23 | /** 24 | * 设置界面 25 | * Created by kangtian on 2018/8/3. 26 | */ 27 | public class GeneratorSettingUI extends JDialog { 28 | public JPanel contentPanel = new JBPanel<>(); 29 | 30 | private Project project; 31 | 32 | private EditorTextFieldWithBrowseButton domainPackageField; 33 | private EditorTextFieldWithBrowseButton mapperPackageField; 34 | private JTextField xmlPackageField = new JTextField(); 35 | private EditorTextFieldWithBrowseButton examplePackageField; 36 | private TextFieldWithBrowseButton moduleRootField = new TextFieldWithBrowseButton(); 37 | 38 | private JTextField sourcePathField = new JTextField(); 39 | private JTextField resourcePathField = new JTextField(); 40 | 41 | private JTextField tablePrefixField = new JTextField(10); 42 | 43 | private JTextField mapperPostfixField = new JTextField(10); 44 | private JTextField examplePostfixField = new JTextField(10); 45 | 46 | private JCheckBox offsetLimitBox = new JCheckBox("Pageable"); 47 | private JCheckBox commentBox = new JCheckBox("Comment"); 48 | private JCheckBox overrideBox = new JCheckBox("Overwrite"); 49 | private JCheckBox needToStringHashcodeEqualsBox = new JCheckBox("toString/hashCode/equals"); 50 | private JCheckBox useSchemaPrefixBox = new JCheckBox("Use Schema Prefix"); 51 | private JCheckBox needForUpdateBox = new JCheckBox("Add ForUpdate"); 52 | private JCheckBox annotationDAOBox = new JCheckBox("Repository Annotation"); 53 | private JCheckBox useDAOExtendStyleBox = new JCheckBox("Parent Interface"); 54 | private JCheckBox jsr310SupportBox = new JCheckBox("JSR310: Date and Time API"); 55 | private JCheckBox annotationBox = new JCheckBox("JPA Annotation"); 56 | private JCheckBox useActualColumnNamesBox = new JCheckBox("Actual-Column"); 57 | private JCheckBox useTableNameAliasBox = new JCheckBox("Use-Alias"); 58 | private JCheckBox useExampleBox = new JCheckBox("Use Example"); 59 | private JCheckBox mysql8Box = new JCheckBox("MySQL 8"); 60 | private JCheckBox lombokAnnotationBox = new JCheckBox("Lombok"); 61 | private JCheckBox lombokBuilderAnnotationBox = new JCheckBox("Lombok Builder"); 62 | private JCheckBox swaggerAnnotationBox = new JCheckBox("Swagger Model"); 63 | 64 | 65 | private MyBatisGeneratorConfiguration config; 66 | 67 | public GeneratorSettingUI() { 68 | setContentPane(contentPanel); 69 | } 70 | 71 | 72 | public void createUI(Project project) { 73 | this.project = project; 74 | contentPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 75 | 76 | config = MyBatisGeneratorConfiguration.getInstance(project); 77 | 78 | this.initPathPanel(); 79 | this.initPostfixPanel(); 80 | this.initPackagePanel(); 81 | this.initOptionsPanel(); 82 | this.initClearCachePanel(); 83 | this.reset(); 84 | } 85 | 86 | private void initOptionsPanel() { 87 | JBPanel optionsPanel = new JBPanel(new GridLayout(6, 2, 10, 10)); 88 | 89 | optionsPanel.add(offsetLimitBox); 90 | optionsPanel.add(commentBox); 91 | optionsPanel.add(overrideBox); 92 | optionsPanel.add(needToStringHashcodeEqualsBox); 93 | optionsPanel.add(useSchemaPrefixBox); 94 | optionsPanel.add(needForUpdateBox); 95 | optionsPanel.add(annotationDAOBox); 96 | optionsPanel.add(useDAOExtendStyleBox); 97 | optionsPanel.add(jsr310SupportBox); 98 | optionsPanel.add(annotationBox); 99 | optionsPanel.add(useActualColumnNamesBox); 100 | optionsPanel.add(useTableNameAliasBox); 101 | optionsPanel.add(useExampleBox); 102 | optionsPanel.add(mysql8Box); 103 | optionsPanel.add(lombokAnnotationBox); 104 | optionsPanel.add(lombokBuilderAnnotationBox); 105 | optionsPanel.add(swaggerAnnotationBox); 106 | 107 | TitledSeparator separator = new TitledSeparator(); 108 | separator.setText("Options"); 109 | contentPanel.add(separator); 110 | contentPanel.add(optionsPanel); 111 | } 112 | 113 | private void initPathPanel() { 114 | 115 | JPanel sourcePathPanel = new JPanel(); 116 | sourcePathPanel.setLayout(new BoxLayout(sourcePathPanel, BoxLayout.X_AXIS)); 117 | JBLabel sourcePathLabel = new JBLabel("Source Path:"); 118 | sourcePathLabel.setPreferredSize(new Dimension(200, 20)); 119 | sourcePathPanel.add(sourcePathLabel); 120 | sourcePathPanel.add(sourcePathField); 121 | 122 | JPanel resourcePathPanel = new JPanel(); 123 | resourcePathPanel.setLayout(new BoxLayout(resourcePathPanel, BoxLayout.X_AXIS)); 124 | JBLabel resourcePathLabel = new JBLabel("Resource Path:"); 125 | resourcePathLabel.setPreferredSize(new Dimension(200, 20)); 126 | resourcePathPanel.add(resourcePathLabel); 127 | resourcePathPanel.add(resourcePathField); 128 | 129 | JPanel pathPanel = new JPanel(); 130 | pathPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 131 | TitledSeparator separator = new TitledSeparator(); 132 | separator.setText("Path"); 133 | pathPanel.add(sourcePathPanel); 134 | pathPanel.add(resourcePathPanel); 135 | contentPanel.add(separator); 136 | contentPanel.add(pathPanel); 137 | } 138 | 139 | private void initClearCachePanel() { 140 | 141 | JPanel clearCachePanel = new JPanel(); 142 | clearCachePanel.setLayout(new BoxLayout(clearCachePanel, BoxLayout.X_AXIS)); 143 | JButton clearCacheButton = new JButton("Clear Generate Setting"); 144 | JBLabel clearCacheLabel = new JBLabel(""); 145 | clearCachePanel.add(clearCacheButton); 146 | clearCachePanel.add(clearCacheLabel); 147 | 148 | clearCacheButton.addActionListener(e -> { 149 | int confirm = Messages.showOkCancelDialog(project, "Confirm clear generate setting?", "Mybatis Generator Plus", Messages.getQuestionIcon()); 150 | if (confirm == 2) { 151 | return; 152 | } 153 | config.setTableConfigs(null); 154 | clearCacheLabel.setText("Clear generate setting successful!"); 155 | }); 156 | TitledSeparator separator = new TitledSeparator(); 157 | separator.setText("Others"); 158 | contentPanel.add(separator); 159 | contentPanel.add(clearCachePanel); 160 | } 161 | 162 | 163 | private void initPostfixPanel() { 164 | 165 | JPanel tablePrefixPanel = new JPanel(); 166 | tablePrefixPanel.setLayout(new BoxLayout(tablePrefixPanel, BoxLayout.X_AXIS)); 167 | JBLabel tablePrefixLabel = new JBLabel("Table Prefix:"); 168 | tablePrefixLabel.setPreferredSize(new Dimension(200, 20)); 169 | tablePrefixPanel.add(tablePrefixLabel); 170 | tablePrefixPanel.add(tablePrefixField); 171 | 172 | JPanel prefixPanel = new JPanel(); 173 | prefixPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 174 | TitledSeparator separator = new TitledSeparator(); 175 | separator.setText("Prefix"); 176 | prefixPanel.add(tablePrefixPanel); 177 | contentPanel.add(separator); 178 | contentPanel.add(prefixPanel); 179 | 180 | 181 | JPanel mapperPostfixPanel = new JPanel(); 182 | mapperPostfixPanel.setLayout(new BoxLayout(mapperPostfixPanel, BoxLayout.X_AXIS)); 183 | JBLabel mapperPostfixLabel = new JBLabel("Mapper Postfix:"); 184 | mapperPostfixLabel.setPreferredSize(new Dimension(200, 20)); 185 | mapperPostfixPanel.add(mapperPostfixLabel); 186 | mapperPostfixPanel.add(mapperPostfixField); 187 | 188 | JPanel examplePostfixPanel = new JPanel(); 189 | examplePostfixPanel.setLayout(new BoxLayout(examplePostfixPanel, BoxLayout.X_AXIS)); 190 | JBLabel examplePostfixLabel = new JBLabel("Example Postfix:"); 191 | examplePostfixLabel.setPreferredSize(new Dimension(200, 20)); 192 | examplePostfixPanel.add(examplePostfixLabel); 193 | examplePostfixPanel.add(examplePostfixField); 194 | 195 | JPanel postfixPanel = new JPanel(); 196 | postfixPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 197 | TitledSeparator separator2 = new TitledSeparator(); 198 | separator2.setText("Postfix"); 199 | postfixPanel.add(mapperPostfixPanel); 200 | postfixPanel.add(examplePostfixPanel); 201 | contentPanel.add(separator2); 202 | contentPanel.add(postfixPanel); 203 | } 204 | 205 | private void initPackagePanel() { 206 | 207 | GlobalConfig globalConfig = config.getGlobalConfig(); 208 | 209 | JPanel projectRootPanel = new JPanel(); 210 | projectRootPanel.setLayout(new BoxLayout(projectRootPanel, BoxLayout.X_AXIS)); 211 | JBLabel projectRootLabel = new JBLabel("Module Root:"); 212 | projectRootLabel.setPreferredSize(new Dimension(200, 20)); 213 | moduleRootField.addBrowseFolderListener(new TextBrowseFolderListener(FileChooserDescriptorFactory.createSingleFolderDescriptor()) { 214 | @Override 215 | public void actionPerformed(ActionEvent e) { 216 | super.actionPerformed(e); 217 | moduleRootField.setText(moduleRootField.getText().replaceAll("\\\\", "/")); 218 | } 219 | }); 220 | if (globalConfig != null && !StringUtils.isEmpty(globalConfig.getModuleRootPath())) { 221 | moduleRootField.setText(globalConfig.getModuleRootPath()); 222 | } else { 223 | moduleRootField.setText(project.getBasePath()); 224 | } 225 | projectRootPanel.add(projectRootLabel); 226 | projectRootPanel.add(moduleRootField); 227 | 228 | JPanel entityPackagePanel = new JPanel(); 229 | entityPackagePanel.setLayout(new BoxLayout(entityPackagePanel, BoxLayout.X_AXIS)); 230 | JBLabel entityPackageLabel = new JBLabel("Domain Package:"); 231 | entityPackageLabel.setPreferredSize(new Dimension(200, 20)); 232 | domainPackageField = new EditorTextFieldWithBrowseButton(project, false); 233 | domainPackageField.addActionListener(e -> { 234 | final PackageChooserDialog chooser = new PackageChooserDialog("Select Domain Package", project); 235 | chooser.selectPackage(domainPackageField.getText()); 236 | chooser.show(); 237 | final PsiPackage psiPackage = chooser.getSelectedPackage(); 238 | String packageName = psiPackage == null ? null : psiPackage.getQualifiedName(); 239 | domainPackageField.setText(packageName); 240 | }); 241 | entityPackagePanel.add(entityPackageLabel); 242 | entityPackagePanel.add(domainPackageField); 243 | 244 | JPanel mapperPackagePanel = new JPanel(); 245 | mapperPackagePanel.setLayout(new BoxLayout(mapperPackagePanel, BoxLayout.X_AXIS)); 246 | JLabel mapperPackageLabel = new JLabel("Mapper Package:"); 247 | mapperPackageLabel.setPreferredSize(new Dimension(200, 20)); 248 | mapperPackageField = new EditorTextFieldWithBrowseButton(project, false); 249 | mapperPackageField.addActionListener(e -> { 250 | final PackageChooserDialog packageChooserDialog = new PackageChooserDialog("Select Mapper Package", project); 251 | packageChooserDialog.selectPackage(mapperPackageField.getText()); 252 | packageChooserDialog.show(); 253 | final PsiPackage psiPackage = packageChooserDialog.getSelectedPackage(); 254 | String packageName = psiPackage == null ? null : psiPackage.getQualifiedName(); 255 | mapperPackageField.setText(packageName); 256 | }); 257 | mapperPackagePanel.add(mapperPackageLabel); 258 | mapperPackagePanel.add(mapperPackageField); 259 | 260 | JPanel examplePackagePanel = new JPanel(); 261 | examplePackagePanel.setLayout(new BoxLayout(examplePackagePanel, BoxLayout.X_AXIS)); 262 | JLabel examplePackageLabel = new JLabel("Example Package:"); 263 | examplePackageLabel.setPreferredSize(new Dimension(200, 20)); 264 | examplePackageField = new EditorTextFieldWithBrowseButton(project, false); 265 | examplePackageField.addActionListener(e -> { 266 | final PackageChooserDialog packageChooserDialog = new PackageChooserDialog("Select Example Package", project); 267 | packageChooserDialog.selectPackage(examplePackageField.getText()); 268 | packageChooserDialog.show(); 269 | final PsiPackage psiPackage = packageChooserDialog.getSelectedPackage(); 270 | String packageName = psiPackage == null ? null : psiPackage.getQualifiedName(); 271 | examplePackageField.setText(packageName); 272 | }); 273 | examplePackagePanel.add(examplePackageLabel); 274 | examplePackagePanel.add(examplePackageField); 275 | 276 | JPanel xmlPackagePanel = new JPanel(); 277 | xmlPackagePanel.setLayout(new BoxLayout(xmlPackagePanel, BoxLayout.X_AXIS)); 278 | JLabel xmlPackageLabel = new JLabel("Xml Package:"); 279 | xmlPackageLabel.setPreferredSize(new Dimension(200, 20)); 280 | xmlPackageField.setText(globalConfig.getXmlPackage()); 281 | xmlPackagePanel.add(xmlPackageLabel); 282 | xmlPackagePanel.add(xmlPackageField); 283 | 284 | JPanel packagePanel = new JPanel(); 285 | packagePanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 286 | packagePanel.add(projectRootPanel); 287 | packagePanel.add(entityPackagePanel); 288 | packagePanel.add(mapperPackagePanel); 289 | packagePanel.add(examplePackagePanel); 290 | packagePanel.add(xmlPackagePanel); 291 | 292 | TitledSeparator separator = new TitledSeparator(); 293 | separator.setText("Package"); 294 | contentPanel.add(separator); 295 | contentPanel.add(packagePanel); 296 | } 297 | 298 | public boolean isModified() { 299 | boolean modified = !this.domainPackageField.getText().equals(config.getGlobalConfig().getDomainPackage()); 300 | modified |= !this.moduleRootField.getText().equals(config.getGlobalConfig().getModuleRootPath()); 301 | modified |= !this.mapperPackageField.getText().equals(config.getGlobalConfig().getMapperPackage()); 302 | modified |= !this.xmlPackageField.getText().equals(config.getGlobalConfig().getXmlPackage()); 303 | modified |= !this.examplePackageField.getText().equals(config.getGlobalConfig().getExamplePackage()); 304 | modified |= !this.mapperPostfixField.getText().equals(config.getGlobalConfig().getMapperPostfix()); 305 | modified |= !this.examplePostfixField.getText().equals(config.getGlobalConfig().getExamplePostfix()); 306 | modified |= !this.tablePrefixField.getText().equals(config.getGlobalConfig().getTablePrefix()); 307 | modified |= !this.sourcePathField.getText().equals(config.getGlobalConfig().getSourcePath()); 308 | modified |= !this.resourcePathField.getText().equals(config.getGlobalConfig().getResourcePath()); 309 | modified |= (this.offsetLimitBox.getSelectedObjects() != null) == (config.getGlobalConfig().isOffsetLimit()); 310 | modified |= (this.commentBox.getSelectedObjects() != null) == (config.getGlobalConfig().isComment()); 311 | modified |= (this.overrideBox.getSelectedObjects() != null) == (config.getGlobalConfig().isOverride()); 312 | modified |= (this.needToStringHashcodeEqualsBox.getSelectedObjects() != null) == (config.getGlobalConfig().isNeedToStringHashcodeEquals()); 313 | modified |= (this.annotationDAOBox.getSelectedObjects() != null) == (config.getGlobalConfig().isAnnotationDAO()); 314 | modified |= (this.useDAOExtendStyleBox.getSelectedObjects() != null) == (config.getGlobalConfig().isUseDAOExtendStyle()); 315 | modified |= (this.jsr310SupportBox.getSelectedObjects() != null) == (config.getGlobalConfig().isJsr310Support()); 316 | modified |= (this.annotationBox.getSelectedObjects() != null) == (config.getGlobalConfig().isAnnotation()); 317 | modified |= (this.useActualColumnNamesBox.getSelectedObjects() != null) == (config.getGlobalConfig().isUseActualColumnNames()); 318 | modified |= (this.useTableNameAliasBox.getSelectedObjects() != null) == (config.getGlobalConfig().isUseTableNameAlias()); 319 | modified |= (this.useExampleBox.getSelectedObjects() != null) == (config.getGlobalConfig().isUseExample()); 320 | modified |= (this.mysql8Box.getSelectedObjects() != null) == (config.getGlobalConfig().isMysql8()); 321 | modified |= (this.lombokAnnotationBox.getSelectedObjects() != null) == (config.getGlobalConfig().isLombokAnnotation()); 322 | modified |= (this.lombokBuilderAnnotationBox.getSelectedObjects() != null) == (config.getGlobalConfig().isLombokBuilderAnnotation()); 323 | modified |= (this.swaggerAnnotationBox.getSelectedObjects() != null) == (config.getGlobalConfig().isSwaggerAnnotation()); 324 | return modified; 325 | } 326 | 327 | public void apply() { 328 | GlobalConfig globalConfig = new GlobalConfig(); 329 | globalConfig.setModuleRootPath(moduleRootField.getText()); 330 | globalConfig.setMapperPostfix(mapperPostfixField.getText()); 331 | globalConfig.setExamplePostfix(examplePostfixField.getText()); 332 | globalConfig.setTablePrefix(tablePrefixField.getText()); 333 | globalConfig.setDomainPackage(domainPackageField.getText()); 334 | globalConfig.setMapperPackage(mapperPackageField.getText()); 335 | globalConfig.setExamplePackage(examplePackageField.getText()); 336 | globalConfig.setXmlPackage(xmlPackageField.getText()); 337 | globalConfig.setOffsetLimit(offsetLimitBox.getSelectedObjects() != null); 338 | globalConfig.setComment(commentBox.getSelectedObjects() != null); 339 | globalConfig.setOverride(overrideBox.getSelectedObjects() != null); 340 | globalConfig.setNeedToStringHashcodeEquals(needToStringHashcodeEqualsBox.getSelectedObjects() != null); 341 | globalConfig.setUseSchemaPrefix(useSchemaPrefixBox.getSelectedObjects() != null); 342 | globalConfig.setNeedForUpdate(needForUpdateBox.getSelectedObjects() != null); 343 | globalConfig.setAnnotationDAO(annotationDAOBox.getSelectedObjects() != null); 344 | globalConfig.setUseDAOExtendStyle(useDAOExtendStyleBox.getSelectedObjects() != null); 345 | globalConfig.setJsr310Support(jsr310SupportBox.getSelectedObjects() != null); 346 | globalConfig.setAnnotation(annotationBox.getSelectedObjects() != null); 347 | globalConfig.setUseActualColumnNames(useActualColumnNamesBox.getSelectedObjects() != null); 348 | globalConfig.setUseTableNameAlias(useTableNameAliasBox.getSelectedObjects() != null); 349 | globalConfig.setUseExample(useExampleBox.getSelectedObjects() != null); 350 | globalConfig.setMysql8(mysql8Box.getSelectedObjects() != null); 351 | globalConfig.setLombokAnnotation(lombokAnnotationBox.getSelectedObjects() != null); 352 | globalConfig.setLombokBuilderAnnotation(lombokBuilderAnnotationBox.getSelectedObjects() != null); 353 | globalConfig.setSwaggerAnnotation(swaggerAnnotationBox.getSelectedObjects() != null); 354 | 355 | globalConfig.setSourcePath(sourcePathField.getText()); 356 | globalConfig.setResourcePath(resourcePathField.getText()); 357 | 358 | this.config.setGlobalConfig(globalConfig); 359 | 360 | 361 | } 362 | 363 | public void reset() { 364 | GlobalConfig globalConfig = config.getGlobalConfig(); 365 | mapperPostfixField.setText(globalConfig.getMapperPostfix()); 366 | examplePostfixField.setText(globalConfig.getExamplePostfix()); 367 | tablePrefixField.setText(globalConfig.getTablePrefix()); 368 | domainPackageField.setText(globalConfig.getDomainPackage()); 369 | mapperPackageField.setText(globalConfig.getMapperPackage()); 370 | examplePackageField.setText(globalConfig.getExamplePackage()); 371 | xmlPackageField.setText(globalConfig.getXmlPackage()); 372 | 373 | sourcePathField.setText(globalConfig.getSourcePath()); 374 | resourcePathField.setText(globalConfig.getResourcePath()); 375 | 376 | offsetLimitBox.setSelected(globalConfig.isOffsetLimit()); 377 | commentBox.setSelected(globalConfig.isComment()); 378 | overrideBox.setSelected(globalConfig.isOverride()); 379 | needToStringHashcodeEqualsBox.setSelected(globalConfig.isNeedToStringHashcodeEquals()); 380 | useSchemaPrefixBox.setSelected(globalConfig.isUseSchemaPrefix()); 381 | needForUpdateBox.setSelected(globalConfig.isNeedForUpdate()); 382 | annotationDAOBox.setSelected(globalConfig.isAnnotationDAO()); 383 | useDAOExtendStyleBox.setSelected(globalConfig.isUseDAOExtendStyle()); 384 | jsr310SupportBox.setSelected(globalConfig.isJsr310Support()); 385 | annotationBox.setSelected(globalConfig.isAnnotation()); 386 | useActualColumnNamesBox.setSelected(globalConfig.isUseActualColumnNames()); 387 | useTableNameAliasBox.setSelected(globalConfig.isUseTableNameAlias()); 388 | useExampleBox.setSelected(globalConfig.isUseExample()); 389 | mysql8Box.setSelected(globalConfig.isMysql8()); 390 | lombokAnnotationBox.setSelected(globalConfig.isLombokAnnotation()); 391 | lombokBuilderAnnotationBox.setSelected(globalConfig.isLombokBuilderAnnotation()); 392 | swaggerAnnotationBox.setSelected(globalConfig.isSwaggerAnnotation()); 393 | 394 | } 395 | 396 | @Override 397 | public JPanel getContentPane() { 398 | return contentPanel; 399 | } 400 | 401 | 402 | } 403 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/generate/MyBatisGenerateCommand.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.generate; 2 | 3 | import cn.kt.DbRemarksCommentGenerator; 4 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableConfig; 5 | import com.intellij.credentialStore.CredentialAttributes; 6 | import com.intellij.database.model.RawConnectionConfig; 7 | import com.intellij.ide.passwordSafe.PasswordSafe; 8 | import com.intellij.notification.*; 9 | import com.intellij.openapi.fileEditor.OpenFileDescriptor; 10 | import com.intellij.openapi.progress.ProgressIndicator; 11 | import com.intellij.openapi.progress.Task; 12 | import com.intellij.openapi.project.Project; 13 | import com.intellij.openapi.ui.MessageType; 14 | import com.intellij.openapi.ui.Messages; 15 | import com.intellij.openapi.ui.popup.Balloon; 16 | import com.intellij.openapi.ui.popup.JBPopupFactory; 17 | import com.intellij.openapi.vfs.VirtualFile; 18 | import com.intellij.openapi.wm.StatusBar; 19 | import com.intellij.openapi.wm.WindowManager; 20 | import com.intellij.ui.awt.RelativePoint; 21 | import com.github.leecho.idea.plugin.mybatis.generator.model.Credential; 22 | import com.github.leecho.idea.plugin.mybatis.generator.model.DbType; 23 | import com.github.leecho.idea.plugin.mybatis.generator.setting.MyBatisGeneratorConfiguration; 24 | import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils; 25 | import org.mybatis.generator.api.ShellCallback; 26 | import org.mybatis.generator.config.*; 27 | import org.mybatis.generator.internal.DefaultShellCallback; 28 | 29 | import javax.swing.event.HyperlinkEvent; 30 | import java.io.File; 31 | import java.util.*; 32 | import java.util.stream.Collectors; 33 | 34 | /** 35 | * 生成mybatis相关代码 36 | * Created by kangtian on 2018/7/28. 37 | */ 38 | public class MyBatisGenerateCommand { 39 | 40 | //持久化的配置 41 | private MyBatisGeneratorConfiguration myBatisGeneratorConfiguration; 42 | //界面默认配置 43 | private TableConfig tableConfig; 44 | private String username; 45 | //数据库类型 46 | private String databaseType; 47 | //数据库驱动 48 | private String driverClass; 49 | //数据库连接url 50 | private String url; 51 | 52 | public MyBatisGenerateCommand(TableConfig tableConfig) { 53 | this.tableConfig = tableConfig; 54 | } 55 | 56 | /** 57 | * 自动生成的主逻辑 58 | * 59 | * @param project 60 | * @param connectionConfig 61 | * @throws Exception 62 | */ 63 | public void execute(Project project, RawConnectionConfig connectionConfig) { 64 | this.myBatisGeneratorConfiguration = MyBatisGeneratorConfiguration.getInstance(project); 65 | 66 | saveConfig();//执行前 先保存一份当前配置 67 | 68 | driverClass = connectionConfig.getDriverClass(); 69 | url = connectionConfig.getUrl(); 70 | if (driverClass.contains("mysql")) { 71 | databaseType = "MySQL"; 72 | } else if (driverClass.contains("oracle")) { 73 | databaseType = "Oracle"; 74 | } else if (driverClass.contains("postgresql")) { 75 | databaseType = "PostgreSQL"; 76 | } else if (driverClass.contains("sqlserver")) { 77 | databaseType = "SqlServer"; 78 | } else if (driverClass.contains("sqlite")) { 79 | databaseType = "Sqlite"; 80 | } else if (driverClass.contains("mariadb")) { 81 | databaseType = "MariaDB"; 82 | } 83 | 84 | 85 | Configuration configuration = new Configuration(); 86 | Context context = new Context(ModelType.CONDITIONAL); 87 | configuration.addContext(context); 88 | 89 | context.setId("myid"); 90 | context.addProperty("autoDelimitKeywords", "true"); 91 | context.addProperty("beginningDelimiter", "`"); 92 | context.addProperty("endingDelimiter", "`"); 93 | context.addProperty("javaFileEncoding", "UTF-8"); 94 | context.addProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING, "UTF-8"); 95 | context.setTargetRuntime("MyBatis3"); 96 | 97 | JDBCConnectionConfiguration jdbcConfig = buildJdbcConfig(); 98 | if (jdbcConfig == null) { 99 | return; 100 | } 101 | TableConfiguration tableConfig = buildTableConfig(context); 102 | JavaModelGeneratorConfiguration modelConfig = buildModelConfig(); 103 | SqlMapGeneratorConfiguration mapperConfig = buildMapperXmlConfig(); 104 | JavaClientGeneratorConfiguration daoConfig = buildMapperConfig(); 105 | CommentGeneratorConfiguration commentConfig = buildCommentConfig(); 106 | 107 | context.addTableConfiguration(tableConfig); 108 | context.setJdbcConnectionConfiguration(jdbcConfig); 109 | context.setJavaModelGeneratorConfiguration(modelConfig); 110 | context.setSqlMapGeneratorConfiguration(mapperConfig); 111 | context.setJavaClientGeneratorConfiguration(daoConfig); 112 | context.setCommentGeneratorConfiguration(commentConfig); 113 | addPluginConfiguration(context); 114 | 115 | createFolderForNeed(this.tableConfig); 116 | List warnings = new ArrayList<>(); 117 | // override=true 118 | ShellCallback shellCallback; 119 | if (this.tableConfig.isOverride()) { 120 | shellCallback = new DefaultShellCallback(true); 121 | } else { 122 | shellCallback = new MergeableShellCallback(true); 123 | } 124 | Set fullyQualifiedTables = new HashSet<>(); 125 | Set contexts = new HashSet<>(); 126 | 127 | try { 128 | MyBatisCodeGenerator myBatisCodeGenerator = new MyBatisCodeGenerator(configuration, shellCallback, warnings); 129 | StatusBar statusBar = WindowManager.getInstance().getStatusBar(project); 130 | Balloon balloon = JBPopupFactory.getInstance() 131 | .createHtmlTextBalloonBuilder("Generating Code...", MessageType.INFO, null) 132 | .createBalloon(); 133 | balloon.show(RelativePoint.getCenterOf(statusBar.getComponent()), Balloon.Position.atRight); 134 | 135 | Task.Backgroundable generateTask = new Task.Backgroundable(project, "Generating MyBatis Code", false) { 136 | @Override 137 | public void run(ProgressIndicator indicator) { 138 | indicator.setText("Generating MyBatis Code"); 139 | indicator.setFraction(0.0); 140 | indicator.setIndeterminate(true); 141 | try { 142 | myBatisCodeGenerator.generate(new GenerateCallback(indicator, balloon), contexts, fullyQualifiedTables); 143 | VirtualFile baseDir = project.getBaseDir(); 144 | baseDir.refresh(false, true); 145 | 146 | NotificationGroup balloonNotifications = new NotificationGroup("Mybatis Generator Plus", NotificationDisplayType.STICKY_BALLOON, true); 147 | 148 | List result = myBatisCodeGenerator.getGeneratedJavaFiles().stream() 149 | .map(generatedJavaFile -> String.format("%s", getRelativePath(project), MyBatisGenerateCommand.this.tableConfig.getSourcePath(), generatedJavaFile.getTargetPackage().replace(".", "/"), generatedJavaFile.getFileName(), generatedJavaFile.getFileName())) 150 | .collect(Collectors.toList()); 151 | result.addAll(myBatisCodeGenerator.getGeneratedXmlFiles().stream() 152 | .map(generatedXmlFile -> String.format("%s", getRelativePath(project).replace(project.getBasePath() + "/", ""), MyBatisGenerateCommand.this.tableConfig.getResourcePath(), generatedXmlFile.getTargetPackage().replace(".", "/"), generatedXmlFile.getFileName(), generatedXmlFile.getFileName())) 153 | .collect(Collectors.toList())); 154 | Notification notification = balloonNotifications.createNotification("Generate Successfully", "" + String.join("
    ", result) + "", NotificationType.INFORMATION, (notification1, hyperlinkEvent) -> { 155 | if (hyperlinkEvent.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 156 | new OpenFileDescriptor(project, Objects.requireNonNull(project.getBaseDir().findFileByRelativePath(hyperlinkEvent.getDescription()))).navigate(true); 157 | } 158 | }); 159 | Notifications.Bus.notify(notification); 160 | } catch (Exception e) { 161 | e.printStackTrace(); 162 | balloon.hide(); 163 | Notification notification = new Notification("Mybatis Generator Plus", null, NotificationType.ERROR); 164 | notification.setTitle("Generate Failed"); 165 | notification.setContent("Cause:" + e.getMessage()); 166 | Notifications.Bus.notify(notification); 167 | } 168 | } 169 | }; 170 | generateTask.setCancelText("Stop generate code").queue(); 171 | generateTask.setCancelTooltipText("Stop generate mybatis code"); 172 | 173 | } catch (Exception e) { 174 | e.printStackTrace(); 175 | Messages.showMessageDialog(e.getMessage(), "Generate Failure", Messages.getInformationIcon()); 176 | } 177 | 178 | } 179 | 180 | private String getRelativePath(Project project) { 181 | if (tableConfig.getModuleRootPath().equals(project.getBasePath())) { 182 | return ""; 183 | } else { 184 | return tableConfig.getModuleRootPath().replace(project.getBasePath() + "/", "") + "/"; 185 | } 186 | } 187 | 188 | 189 | /** 190 | * 创建所需目录 191 | * 192 | * @param tableConfig 193 | */ 194 | private void createFolderForNeed(TableConfig tableConfig) { 195 | 196 | 197 | String sourcePath = tableConfig.getModuleRootPath() + "/" + tableConfig.getSourcePath() + "/"; 198 | String resourcePath = tableConfig.getModuleRootPath() + "/" + tableConfig.getResourcePath() + "/"; 199 | 200 | File sourceFile = new File(sourcePath); 201 | if (!sourceFile.exists() && !sourceFile.isDirectory()) { 202 | sourceFile.mkdirs(); 203 | } 204 | 205 | File resourceFile = new File(resourcePath); 206 | if (!resourceFile.exists() && !resourceFile.isDirectory()) { 207 | resourceFile.mkdirs(); 208 | } 209 | } 210 | 211 | 212 | /** 213 | * 保存当前配置到历史记录 214 | */ 215 | private void saveConfig() { 216 | Map historyConfigList = myBatisGeneratorConfiguration.getTableConfigs(); 217 | if (historyConfigList == null) { 218 | historyConfigList = new HashMap<>(); 219 | } 220 | 221 | String daoName = tableConfig.getMapperName(); 222 | String modelName = tableConfig.getDomainName(); 223 | String daoPostfix = daoName.replace(modelName, ""); 224 | tableConfig.setMapperPostfix(daoPostfix); 225 | 226 | historyConfigList.put(tableConfig.getName(), tableConfig); 227 | myBatisGeneratorConfiguration.setTableConfigs(historyConfigList); 228 | 229 | } 230 | 231 | /** 232 | * 生成数据库连接配置 233 | * 234 | * @return 235 | */ 236 | private JDBCConnectionConfiguration buildJdbcConfig() { 237 | 238 | JDBCConnectionConfiguration jdbcConfig = new JDBCConnectionConfiguration(); 239 | jdbcConfig.addProperty("nullCatalogMeansCurrent", "true"); 240 | jdbcConfig.addProperty("remarks","true"); 241 | jdbcConfig.addProperty("useInformationSchema","true"); 242 | 243 | Map users = myBatisGeneratorConfiguration.getCredentials(); 244 | //if (users != null && users.containsKey(url)) { 245 | Credential credential = users.get(url); 246 | 247 | username = credential.getUsername(); 248 | 249 | CredentialAttributes credentialAttributes = new CredentialAttributes("mybatis-generator-" + url, username, this.getClass(), false); 250 | String password = PasswordSafe.getInstance().getPassword(credentialAttributes); 251 | 252 | jdbcConfig.setUserId(username); 253 | jdbcConfig.setPassword(password); 254 | 255 | Boolean mySQL_8 = tableConfig.isMysql8(); 256 | if (mySQL_8) { 257 | driverClass = DbType.MySQL_8.getDriverClass(); 258 | url += "?serverTimezone=UTC&useSSL=false"; 259 | } else { 260 | url += "?useSSL=false"; 261 | } 262 | 263 | jdbcConfig.setDriverClass(driverClass); 264 | jdbcConfig.setConnectionURL(url); 265 | return jdbcConfig; 266 | /*} else { 267 | DatabaseCredentialUI databaseCredentialUI = new DatabaseCredentialUI(driverClass, url, anActionEvent, tableConfig); 268 | return null; 269 | }*/ 270 | 271 | } 272 | 273 | /** 274 | * 生成table配置 275 | * 276 | * @param context 277 | * @return 278 | */ 279 | private TableConfiguration buildTableConfig(Context context) { 280 | TableConfiguration tableConfig = new TableConfiguration(context); 281 | tableConfig.setTableName(this.tableConfig.getTableName()); 282 | tableConfig.setDomainObjectName(this.tableConfig.getDomainName()); 283 | 284 | String schema; 285 | if (databaseType.equals(DbType.MySQL.name())) { 286 | String[] name_split = url.split("/"); 287 | schema = name_split[name_split.length - 1]; 288 | tableConfig.setSchema(schema); 289 | } else if (databaseType.equals(DbType.Oracle.name())) { 290 | String[] name_split = url.split(":"); 291 | schema = name_split[name_split.length - 1]; 292 | tableConfig.setCatalog(schema); 293 | } else { 294 | String[] name_split = url.split("/"); 295 | schema = name_split[name_split.length - 1]; 296 | tableConfig.setCatalog(schema); 297 | } 298 | 299 | if (!this.tableConfig.isUseExample()) { 300 | tableConfig.setUpdateByExampleStatementEnabled(false); 301 | tableConfig.setCountByExampleStatementEnabled(false); 302 | tableConfig.setDeleteByExampleStatementEnabled(false); 303 | tableConfig.setSelectByExampleStatementEnabled(false); 304 | } 305 | 306 | if (this.tableConfig.isUseSchemaPrefix()) { 307 | if (DbType.MySQL.name().equals(databaseType)) { 308 | tableConfig.setSchema(schema); 309 | } else if (DbType.Oracle.name().equals(databaseType)) { 310 | //Oracle的schema为用户名,如果连接用户拥有dba等高级权限,若不设schema,会导致把其他用户下同名的表也生成一遍导致mapper中代码重复 311 | tableConfig.setSchema(username); 312 | } else { 313 | tableConfig.setCatalog(schema); 314 | } 315 | } 316 | 317 | if(this.tableConfig.getColumnSettings().size() > 0){ 318 | this.tableConfig.getColumnSettings().forEach((key, value) -> { 319 | if(value.getIgnore()){ 320 | tableConfig.addIgnoredColumn(new IgnoredColumn(value.getColumn())); 321 | } else{ 322 | ColumnOverride override = new ColumnOverride(value.getColumn()); 323 | override.setJavaProperty(value.getJavaProperty()); 324 | override.setJavaType(value.getJavaType()); 325 | override.setJdbcType(value.getJdbcType()); 326 | tableConfig.addColumnOverride(override); 327 | } 328 | 329 | }); 330 | } 331 | 332 | if ("org.postgresql.Driver".equals(driverClass)) { 333 | tableConfig.setDelimitIdentifiers(true); 334 | } 335 | 336 | if (!StringUtils.isEmpty(this.tableConfig.getPrimaryKey())) { 337 | String dbType = databaseType; 338 | if (DbType.MySQL.name().equals(databaseType)) { 339 | dbType = "JDBC"; 340 | //dbType为JDBC,且配置中开启useGeneratedKeys时,Mybatis会使用Jdbc3KeyGenerator, 341 | //使用该KeyGenerator的好处就是直接在一次INSERT 语句内,通过resultSet获取得到 生成的主键值, 342 | //并很好的支持设置了读写分离代理的数据库 343 | //例如阿里云RDS + 读写分离代理 无需指定主库 344 | //当使用SelectKey时,Mybatis会使用SelectKeyGenerator,INSERT之后,多发送一次查询语句,获得主键值 345 | //在上述读写分离被代理的情况下,会得不到正确的主键 346 | } 347 | tableConfig.setGeneratedKey(new GeneratedKey(this.tableConfig.getPrimaryKey(), dbType, true, null)); 348 | } 349 | 350 | if (this.tableConfig.isUseActualColumnNames()) { 351 | tableConfig.addProperty("useActualColumnNames", "true"); 352 | } 353 | 354 | if (this.tableConfig.isUseTableNameAlias()) { 355 | tableConfig.setAlias(this.tableConfig.getTableName()); 356 | } 357 | tableConfig.setMapperName(this.tableConfig.getMapperName()); 358 | return tableConfig; 359 | } 360 | 361 | 362 | /** 363 | * 生成实体类配置 364 | * 365 | * @return 366 | */ 367 | private JavaModelGeneratorConfiguration buildModelConfig() { 368 | String projectFolder = tableConfig.getModuleRootPath(); 369 | String entityPackage = tableConfig.getDomainPackage(); 370 | String sourcePath = tableConfig.getSourcePath(); 371 | 372 | JavaModelGeneratorConfiguration modelConfig = new JavaModelGeneratorConfiguration(); 373 | 374 | if (!StringUtils.isEmpty(entityPackage)) { 375 | modelConfig.setTargetPackage(entityPackage); 376 | } else { 377 | modelConfig.setTargetPackage(""); 378 | } 379 | modelConfig.setTargetProject(projectFolder + "/" + sourcePath + "/"); 380 | return modelConfig; 381 | } 382 | 383 | /** 384 | * 生成mapper.xml文件配置 385 | * 386 | * @return 387 | */ 388 | private SqlMapGeneratorConfiguration buildMapperXmlConfig() { 389 | 390 | String projectFolder = tableConfig.getModuleRootPath(); 391 | String mappingXMLPackage = tableConfig.getXmlPackage(); 392 | String resourcePath = tableConfig.getResourcePath(); 393 | 394 | SqlMapGeneratorConfiguration mapperConfig = new SqlMapGeneratorConfiguration(); 395 | 396 | if (!StringUtils.isEmpty(mappingXMLPackage)) { 397 | mapperConfig.setTargetPackage(mappingXMLPackage); 398 | } else { 399 | mapperConfig.setTargetPackage(""); 400 | } 401 | 402 | mapperConfig.setTargetProject(projectFolder + "/" + resourcePath + "/"); 403 | 404 | //14 405 | if (tableConfig.isOverride()) { 406 | String mappingXMLFilePath = getMappingXMLFilePath(tableConfig); 407 | File mappingXMLFile = new File(mappingXMLFilePath); 408 | if (mappingXMLFile.exists()) { 409 | mappingXMLFile.delete(); 410 | } 411 | } 412 | 413 | return mapperConfig; 414 | } 415 | 416 | /** 417 | * 生成dao接口文件配置 418 | * 419 | * @return 420 | */ 421 | private JavaClientGeneratorConfiguration buildMapperConfig() { 422 | 423 | String projectFolder = tableConfig.getModuleRootPath(); 424 | String mapperPackage = tableConfig.getMapperPackage(); 425 | String mapperPath = tableConfig.getSourcePath(); 426 | 427 | JavaClientGeneratorConfiguration mapperConfig = new JavaClientGeneratorConfiguration(); 428 | mapperConfig.setConfigurationType("XMLMAPPER"); 429 | mapperConfig.setTargetPackage(mapperPackage); 430 | 431 | if (!StringUtils.isEmpty(mapperPackage)) { 432 | mapperConfig.setTargetPackage(mapperPackage); 433 | } else { 434 | mapperConfig.setTargetPackage(""); 435 | } 436 | 437 | mapperConfig.setTargetProject(projectFolder + "/" + mapperPath + "/"); 438 | 439 | return mapperConfig; 440 | } 441 | 442 | /** 443 | * 生成注释配置 444 | * 445 | * @return 446 | */ 447 | private CommentGeneratorConfiguration buildCommentConfig() { 448 | CommentGeneratorConfiguration commentConfig = new CommentGeneratorConfiguration(); 449 | commentConfig.setConfigurationType(DbRemarksCommentGenerator.class.getName()); 450 | 451 | if (tableConfig.isComment()) { 452 | commentConfig.addProperty("columnRemarks", "true"); 453 | } 454 | if (tableConfig.isAnnotation()) { 455 | commentConfig.addProperty("annotations", "true"); 456 | } 457 | 458 | return commentConfig; 459 | } 460 | 461 | /** 462 | * 添加相关插件(注意插件文件需要通过jar引入) 463 | * 464 | * @param context 465 | */ 466 | private void addPluginConfiguration(Context context) { 467 | 468 | 469 | //实体添加序列化 470 | PluginConfiguration serializablePlugin = new PluginConfiguration(); 471 | serializablePlugin.addProperty("type", "org.mybatis.generator.plugins.SerializablePlugin"); 472 | serializablePlugin.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin"); 473 | context.addPluginConfiguration(serializablePlugin); 474 | 475 | 476 | if (tableConfig.isNeedToStringHashcodeEquals()) { 477 | PluginConfiguration equalsHashCodePlugin = new PluginConfiguration(); 478 | equalsHashCodePlugin.addProperty("type", "org.mybatis.generator.plugins.EqualsHashCodePlugin"); 479 | equalsHashCodePlugin.setConfigurationType("org.mybatis.generator.plugins.EqualsHashCodePlugin"); 480 | context.addPluginConfiguration(equalsHashCodePlugin); 481 | PluginConfiguration toStringPluginPlugin = new PluginConfiguration(); 482 | toStringPluginPlugin.addProperty("type", "org.mybatis.generator.plugins.ToStringPlugin"); 483 | toStringPluginPlugin.setConfigurationType("org.mybatis.generator.plugins.ToStringPlugin"); 484 | context.addPluginConfiguration(toStringPluginPlugin); 485 | } 486 | 487 | if (tableConfig.isLombokAnnotation()) { 488 | PluginConfiguration lombokPlugin = new PluginConfiguration(); 489 | lombokPlugin.addProperty("type", "com.github.leecho.idea.plugin.mybatis.generator.plugin.LombokPlugin"); 490 | lombokPlugin.setConfigurationType("com.github.leecho.idea.plugin.mybatis.generator.plugin.LombokPlugin"); 491 | if (tableConfig.isLombokBuilderAnnotation()) { 492 | lombokPlugin.addProperty("builder", "true"); 493 | lombokPlugin.addProperty("allArgsConstructor", "true"); 494 | lombokPlugin.addProperty("noArgsConstructor", "true"); 495 | } 496 | context.addPluginConfiguration(lombokPlugin); 497 | } 498 | if (tableConfig.isSwaggerAnnotation()) { 499 | PluginConfiguration swaggerPlugin = new PluginConfiguration(); 500 | swaggerPlugin.addProperty("type", "com.github.leecho.idea.plugin.mybatis.generator.plugin.SwaggerPlugin"); 501 | swaggerPlugin.setConfigurationType("com.github.leecho.idea.plugin.mybatis.generator.plugin.SwaggerPlugin"); 502 | context.addPluginConfiguration(swaggerPlugin); 503 | } 504 | 505 | if (tableConfig.isUseExample()) { 506 | PluginConfiguration renameExamplePlugin = new PluginConfiguration(); 507 | renameExamplePlugin.addProperty("type", "com.github.leecho.idea.plugin.mybatis.generator.plugin.RenameExampleClassPlugin"); 508 | renameExamplePlugin.setConfigurationType("com.github.leecho.idea.plugin.mybatis.generator.plugin.RenameExampleClassPlugin"); 509 | renameExamplePlugin.addProperty("target", tableConfig.getExamplePackage() + "." + tableConfig.getExampleName()); 510 | context.addPluginConfiguration(renameExamplePlugin); 511 | } 512 | 513 | 514 | // limit/offset插件 515 | if (tableConfig.isOffsetLimit()) { 516 | if (DbType.MySQL.name().equals(databaseType) 517 | || DbType.PostgreSQL.name().equals(databaseType)) { 518 | PluginConfiguration mySQLLimitPlugin = new PluginConfiguration(); 519 | mySQLLimitPlugin.addProperty("type", "cn.kt.MySQLLimitPlugin"); 520 | mySQLLimitPlugin.setConfigurationType("cn.kt.MySQLLimitPlugin"); 521 | context.addPluginConfiguration(mySQLLimitPlugin); 522 | } 523 | } 524 | 525 | //for JSR310 526 | if (tableConfig.isJsr310Support()) { 527 | JavaTypeResolverConfiguration javaTypeResolverPlugin = new JavaTypeResolverConfiguration(); 528 | javaTypeResolverPlugin.setConfigurationType("cn.kt.JavaTypeResolverJsr310Impl"); 529 | context.setJavaTypeResolverConfiguration(javaTypeResolverPlugin); 530 | } 531 | 532 | //forUpdate 插件 533 | if (tableConfig.isNeedForUpdate()) { 534 | if (DbType.MySQL.name().equals(databaseType) 535 | || DbType.PostgreSQL.name().equals(databaseType)) { 536 | PluginConfiguration mySQLForUpdatePlugin = new PluginConfiguration(); 537 | mySQLForUpdatePlugin.addProperty("type", "cn.kt.MySQLForUpdatePlugin"); 538 | mySQLForUpdatePlugin.setConfigurationType("cn.kt.MySQLForUpdatePlugin"); 539 | context.addPluginConfiguration(mySQLForUpdatePlugin); 540 | } 541 | } 542 | 543 | //repository 插件 544 | if (tableConfig.isAnnotationDAO()) { 545 | if (DbType.MySQL.name().equals(databaseType) 546 | || DbType.PostgreSQL.name().equals(databaseType)) { 547 | PluginConfiguration repositoryPlugin = new PluginConfiguration(); 548 | repositoryPlugin.addProperty("type", "cn.kt.RepositoryPlugin"); 549 | repositoryPlugin.setConfigurationType("cn.kt.RepositoryPlugin"); 550 | context.addPluginConfiguration(repositoryPlugin); 551 | } 552 | } 553 | 554 | //13 555 | if (tableConfig.isUseDAOExtendStyle()) { 556 | if (DbType.MySQL.name().equals(databaseType) 557 | || DbType.PostgreSQL.name().equals(databaseType)) { 558 | PluginConfiguration commonDAOInterfacePlugin = new PluginConfiguration(); 559 | commonDAOInterfacePlugin.addProperty("type", "cn.kt.CommonDAOInterfacePlugin"); 560 | commonDAOInterfacePlugin.setConfigurationType("cn.kt.CommonDAOInterfacePlugin"); 561 | context.addPluginConfiguration(commonDAOInterfacePlugin); 562 | } 563 | } 564 | 565 | } 566 | 567 | /** 568 | * 获取xml文件路径 用以删除之前的xml 569 | * 570 | * @param tableConfig 571 | * @return 572 | */ 573 | private String getMappingXMLFilePath(TableConfig tableConfig) { 574 | StringBuilder sb = new StringBuilder(); 575 | String mappingXMLPackage = tableConfig.getXmlPackage(); 576 | String xmlMvnPath = tableConfig.getResourcePath(); 577 | sb.append(tableConfig.getModuleRootPath() + "/" + xmlMvnPath + "/"); 578 | 579 | if (!StringUtils.isEmpty(mappingXMLPackage)) { 580 | sb.append(mappingXMLPackage.replace(".", "/")).append("/"); 581 | } 582 | if (!StringUtils.isEmpty(tableConfig.getMapperName())) { 583 | sb.append(tableConfig.getMapperName()).append(".xml"); 584 | } else { 585 | sb.append(tableConfig.getDomainName()).append("Mapper.xml"); 586 | } 587 | 588 | return sb.toString(); 589 | } 590 | } 591 | -------------------------------------------------------------------------------- /src/com/github/leecho/idea/plugin/mybatis/generator/ui/GenerateSettingUI.java: -------------------------------------------------------------------------------- 1 | package com.github.leecho.idea.plugin.mybatis.generator.ui; 2 | 3 | import com.github.leecho.idea.plugin.mybatis.generator.contants.PluginContants; 4 | import com.github.leecho.idea.plugin.mybatis.generator.generate.MyBatisGenerateCommand; 5 | import com.github.leecho.idea.plugin.mybatis.generator.model.Credential; 6 | import com.github.leecho.idea.plugin.mybatis.generator.model.GlobalConfig; 7 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableConfig; 8 | import com.github.leecho.idea.plugin.mybatis.generator.model.TableInfo; 9 | import com.github.leecho.idea.plugin.mybatis.generator.setting.MyBatisGeneratorConfiguration; 10 | import com.github.leecho.idea.plugin.mybatis.generator.util.DatabaseUtils; 11 | import com.github.leecho.idea.plugin.mybatis.generator.util.JTextFieldHintListener; 12 | import com.github.leecho.idea.plugin.mybatis.generator.util.StringUtils; 13 | import com.intellij.credentialStore.CredentialAttributes; 14 | import com.intellij.database.model.RawConnectionConfig; 15 | import com.intellij.database.psi.DbDataSource; 16 | import com.intellij.database.psi.DbTable; 17 | import com.intellij.ide.passwordSafe.PasswordSafe; 18 | import com.intellij.ide.util.PackageChooserDialog; 19 | import com.intellij.openapi.actionSystem.AnActionEvent; 20 | import com.intellij.openapi.actionSystem.LangDataKeys; 21 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 22 | import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; 23 | import com.intellij.openapi.progress.ProgressManager; 24 | import com.intellij.openapi.project.Project; 25 | import com.intellij.openapi.ui.*; 26 | import com.intellij.psi.PsiElement; 27 | import com.intellij.psi.PsiPackage; 28 | import com.intellij.ui.EditorTextFieldWithBrowseButton; 29 | import com.intellij.ui.TitledSeparator; 30 | import com.intellij.ui.components.JBLabel; 31 | import com.intellij.ui.components.JBPanel; 32 | import com.intellij.ui.components.JBTabbedPane; 33 | import com.intellij.ui.components.JBTextField; 34 | import com.intellij.util.ui.JBUI; 35 | import org.jetbrains.annotations.NotNull; 36 | import org.jetbrains.annotations.Nullable; 37 | 38 | import javax.swing.*; 39 | import java.awt.*; 40 | import java.awt.event.ActionEvent; 41 | import java.awt.event.KeyAdapter; 42 | import java.awt.event.KeyEvent; 43 | import java.sql.SQLException; 44 | import java.util.ArrayList; 45 | import java.util.List; 46 | import java.util.Map; 47 | import java.util.concurrent.Callable; 48 | import java.util.concurrent.ExecutionException; 49 | import java.util.concurrent.FutureTask; 50 | 51 | /** 52 | * 插件主界面 53 | * Created by kangtian on 2018/8/1. 54 | */ 55 | public class GenerateSettingUI extends DialogWrapper { 56 | 57 | private AnActionEvent anActionEvent; 58 | private Project project; 59 | private MyBatisGeneratorConfiguration myBatisGeneratorConfiguration; 60 | private PsiElement[] psiElements; 61 | private TableConfig tableConfig; 62 | 63 | private JPanel contentPane = new JBPanel<>(); 64 | 65 | private JTextField tableNameField = new JBTextField(20); 66 | 67 | private JButton columnSettingButton = new JButton("Column Setting"); 68 | private TextFieldWithBrowseButton moduleRootField = new TextFieldWithBrowseButton(); 69 | private EditorTextFieldWithBrowseButton basePackageField; 70 | private EditorTextFieldWithBrowseButton domainPackageField; 71 | private EditorTextFieldWithBrowseButton mapperPackageField; 72 | private EditorTextFieldWithBrowseButton examplePackageField; 73 | private JTextField xmlPackageField = new JTextField(); 74 | private JTextField mapperNameField = new JBTextField(20); 75 | private JTextField domainNameField = new JBTextField(20); 76 | private JTextField exampleNameField = new JBTextField(20); 77 | private JTextField primaryKeyField = new JBTextField(20); 78 | 79 | private JPanel examplePackagePanel = new JPanel(); 80 | private JPanel exampleNamePanel = new JPanel(); 81 | 82 | private JCheckBox offsetLimitBox = new JCheckBox("Pageable"); 83 | private JCheckBox commentBox = new JCheckBox("Comment"); 84 | private JCheckBox overrideBox = new JCheckBox("Overwrite"); 85 | private JCheckBox needToStringHashcodeEqualsBox = new JCheckBox("toString/hashCode/equals"); 86 | private JCheckBox useSchemaPrefixBox = new JCheckBox("Use Schema Prefix"); 87 | private JCheckBox needForUpdateBox = new JCheckBox("Add ForUpdate"); 88 | private JCheckBox annotationDAOBox = new JCheckBox("Repository Annotation"); 89 | private JCheckBox useDAOExtendStyleBox = new JCheckBox("Parent Interface"); 90 | private JCheckBox jsr310SupportBox = new JCheckBox("JSR310: Date and Time API"); 91 | private JCheckBox annotationBox = new JCheckBox("JPA Annotation"); 92 | private JCheckBox useActualColumnNamesBox = new JCheckBox("Actual-Column"); 93 | private JCheckBox useTableNameAliasBox = new JCheckBox("Use-Alias"); 94 | private JCheckBox useExampleBox = new JCheckBox("Use Example"); 95 | private JCheckBox mysql8Box = new JCheckBox("MySQL 8"); 96 | private JCheckBox lombokAnnotationBox = new JCheckBox("Lombok"); 97 | private JCheckBox lombokBuilderAnnotationBox = new JCheckBox("Lombok Builder"); 98 | private JCheckBox swaggerAnnotationBox = new JCheckBox("Swagger Model"); 99 | private JBTabbedPane tabpanel = new JBTabbedPane(); 100 | 101 | 102 | public GenerateSettingUI(AnActionEvent anActionEvent) { 103 | super(anActionEvent.getData(PlatformDataKeys.PROJECT)); 104 | Project project = anActionEvent.getData(PlatformDataKeys.PROJECT); 105 | this.anActionEvent = anActionEvent; 106 | this.project = anActionEvent.getData(PlatformDataKeys.PROJECT); 107 | this.myBatisGeneratorConfiguration = MyBatisGeneratorConfiguration.getInstance(project); 108 | this.psiElements = anActionEvent.getData(LangDataKeys.PSI_ELEMENT_ARRAY); 109 | 110 | GlobalConfig globalConfig = myBatisGeneratorConfiguration.getGlobalConfig(); 111 | Map historyConfigList = myBatisGeneratorConfiguration.getTableConfigs(); 112 | 113 | setTitle("MyBatis Generator Plus"); 114 | //设置大小 115 | pack(); 116 | setModal(true); 117 | 118 | PsiElement psiElement = psiElements[0]; 119 | TableInfo tableInfo = new TableInfo((DbTable) psiElement); 120 | String tableName = tableInfo.getTableName(); 121 | String realTableName; 122 | if (globalConfig.getTablePrefix() != null && tableName.startsWith(globalConfig.getTablePrefix())) { 123 | realTableName = tableName.substring(globalConfig.getTablePrefix().length()); 124 | } else { 125 | realTableName = tableName; 126 | } 127 | String entityName = StringUtils.dbStringToCamelStyle(realTableName); 128 | String primaryKey = ""; 129 | if (tableInfo.getPrimaryKeys().size() > 0) { 130 | primaryKey = tableInfo.getPrimaryKeys().get(0); 131 | } 132 | 133 | //单表时,优先使用已经存在的配置 134 | if (historyConfigList != null) { 135 | tableConfig = historyConfigList.get(tableName); 136 | } 137 | if (tableConfig == null) { 138 | //初始化配置 139 | tableConfig = new TableConfig(); 140 | tableConfig.setModuleRootPath(globalConfig.getModuleRootPath()); 141 | tableConfig.setSourcePath(globalConfig.getSourcePath()); 142 | tableConfig.setResourcePath(globalConfig.getResourcePath()); 143 | tableConfig.setDomainPackage(globalConfig.getDomainPackage()); 144 | tableConfig.setMapperPackage(globalConfig.getMapperPackage()); 145 | tableConfig.setMapperPostfix(globalConfig.getMapperPostfix()); 146 | tableConfig.setExamplePostfix(globalConfig.getExamplePostfix()); 147 | tableConfig.setExamplePackage(globalConfig.getExamplePackage()); 148 | tableConfig.setXmlPackage(globalConfig.getXmlPackage()); 149 | 150 | tableConfig.setOffsetLimit(globalConfig.isOffsetLimit()); 151 | tableConfig.setComment(globalConfig.isComment()); 152 | tableConfig.setOverride(globalConfig.isOverride()); 153 | tableConfig.setNeedToStringHashcodeEquals(globalConfig.isNeedToStringHashcodeEquals()); 154 | tableConfig.setUseSchemaPrefix(globalConfig.isUseSchemaPrefix()); 155 | tableConfig.setNeedForUpdate(globalConfig.isNeedForUpdate()); 156 | tableConfig.setAnnotationDAO(globalConfig.isAnnotationDAO()); 157 | tableConfig.setUseDAOExtendStyle(globalConfig.isUseDAOExtendStyle()); 158 | tableConfig.setJsr310Support(globalConfig.isJsr310Support()); 159 | tableConfig.setAnnotation(globalConfig.isAnnotation()); 160 | tableConfig.setUseActualColumnNames(globalConfig.isUseActualColumnNames()); 161 | tableConfig.setUseTableNameAlias(globalConfig.isUseTableNameAlias()); 162 | tableConfig.setUseExample(globalConfig.isUseExample()); 163 | tableConfig.setMysql8(globalConfig.isMysql8()); 164 | tableConfig.setLombokAnnotation(globalConfig.isLombokAnnotation()); 165 | tableConfig.setLombokBuilderAnnotation(globalConfig.isLombokBuilderAnnotation()); 166 | tableConfig.setSwaggerAnnotation(globalConfig.isSwaggerAnnotation()); 167 | tableConfig.setPrimaryKey(primaryKey); 168 | } 169 | VerticalFlowLayout layoutManager = new VerticalFlowLayout(VerticalFlowLayout.TOP); 170 | layoutManager.setHgap(0); 171 | layoutManager.setVgap(0); 172 | contentPane.setLayout(layoutManager); 173 | this.initHeader(tableName, primaryKey); 174 | this.initGeneralPanel(entityName); 175 | this.initOptionsPanel(); 176 | tabpanel.add(new ColumnTablePanel(tableConfig, tableInfo)); 177 | contentPane.add(tabpanel); 178 | tabpanel.setUI(new GenerateSettingTabUI()); 179 | contentPane.setBorder(JBUI.Borders.empty()); 180 | this.init(); 181 | } 182 | 183 | @NotNull 184 | @Override 185 | protected DialogStyle getStyle() { 186 | return DialogStyle.COMPACT; 187 | } 188 | 189 | private List validateSetting() { 190 | List errors = new ArrayList<>(); 191 | 192 | if (StringUtils.isEmpty(moduleRootField.getText())) { 193 | errors.add("Module root must not be null"); 194 | } 195 | 196 | if (StringUtils.isEmpty(domainNameField.getText())) { 197 | errors.add("Domain name must not be null"); 198 | } 199 | 200 | if (StringUtils.isEmpty(mapperNameField.getText())) { 201 | errors.add("Mapper name must not be null"); 202 | } 203 | 204 | if (StringUtils.isEmpty(domainPackageField.getText())) { 205 | errors.add("Domain package must not be null"); 206 | } 207 | 208 | if (StringUtils.isEmpty(mapperPackageField.getText())) { 209 | errors.add("Mapper package must not be null"); 210 | } 211 | 212 | if (StringUtils.isEmpty(xmlPackageField.getText())) { 213 | errors.add("Mapper xml package must not be null"); 214 | } 215 | 216 | if (useExampleBox.getSelectedObjects() != null) { 217 | if (StringUtils.isEmpty(exampleNameField.getText())) { 218 | errors.add("Example name must not be null"); 219 | } 220 | if (StringUtils.isEmpty(examplePackageField.getText())) { 221 | errors.add("Example package must not be null"); 222 | } 223 | } 224 | return errors; 225 | } 226 | 227 | @Override 228 | protected void doOKAction() { 229 | 230 | List errors = this.validateSetting(); 231 | if (!errors.isEmpty()) { 232 | Messages.showMessageDialog("Invalid setting: \n" + String.join("\n", errors), "Mybatis Generator Plus", Messages.getWarningIcon()); 233 | return; 234 | } 235 | 236 | DbDataSource dbDataSource = null; 237 | PsiElement current = psiElements[0]; 238 | while (current != null) { 239 | if (DbDataSource.class.isAssignableFrom(current.getClass())) { 240 | dbDataSource = (DbDataSource) current; 241 | break; 242 | } 243 | current = current.getParent(); 244 | } 245 | 246 | if (dbDataSource == null) { 247 | Messages.showMessageDialog(project, "Cannot get datasource", "Mybatis Generator Plus", Messages.getErrorIcon()); 248 | return; 249 | } 250 | 251 | RawConnectionConfig connectionConfig = dbDataSource.getConnectionConfig(); 252 | 253 | if (connectionConfig == null) { 254 | Messages.showMessageDialog(project, "Cannot get connection config", "Mybatis Generator Plus", Messages.getErrorIcon()); 255 | return; 256 | } 257 | 258 | Map credentials = myBatisGeneratorConfiguration.getCredentials(); 259 | Credential credential; 260 | if (credentials == null || !credentials.containsKey(connectionConfig.getUrl())) { 261 | boolean result = getDatabaseCredential(connectionConfig); 262 | if (result) { 263 | credentials = myBatisGeneratorConfiguration.getCredentials(); 264 | credential = credentials.get(connectionConfig.getUrl()); 265 | } else { 266 | return; 267 | } 268 | } else { 269 | credential = credentials.get(connectionConfig.getUrl()); 270 | } 271 | Callable callable = new Callable() { 272 | @Override 273 | public Exception call() { 274 | String url = connectionConfig.getUrl(); 275 | CredentialAttributes credentialAttributes = new CredentialAttributes(PluginContants.PLUGIN_NAME + "-" + url, credential.getUsername(), this.getClass(), false); 276 | String password = PasswordSafe.getInstance().getPassword(credentialAttributes); 277 | try { 278 | DatabaseUtils.testConnection(connectionConfig.getDriverClass(), connectionConfig.getUrl(), credential.getUsername(), password, mysql8Box.getSelectedObjects() != null); 279 | } catch (ClassNotFoundException | SQLException e) { 280 | return e; 281 | } 282 | return null; 283 | } 284 | }; 285 | FutureTask future = new FutureTask<>(callable); 286 | ProgressManager.getInstance().runProcessWithProgressSynchronously(future, "Connect to Database", true, project); 287 | Exception exception; 288 | try { 289 | exception = future.get(); 290 | } catch (InterruptedException | ExecutionException e) { 291 | Messages.showMessageDialog(project, "Failed to connect to database \n " + e.getMessage(), "Mybatis Generator Plus", Messages.getErrorIcon()); 292 | return; 293 | } 294 | if (exception != null) { 295 | Messages.showMessageDialog(project, "Failed to connect to database \n " + exception.getMessage(), "Mybatis Generator Plus", Messages.getErrorIcon()); 296 | if (exception.getClass().equals(SQLException.class)) { 297 | SQLException sqlException = (SQLException) exception; 298 | if (sqlException.getErrorCode() == 1045) { 299 | boolean result = getDatabaseCredential(connectionConfig); 300 | if (result) { 301 | this.doOKAction(); 302 | return; 303 | } 304 | } 305 | } 306 | return; 307 | } 308 | 309 | if (overrideBox.getSelectedObjects() != null) { 310 | int confirm = Messages.showOkCancelDialog(project, "The exists file will be overwrite ,Confirm generate?", "Mybatis Generator Plus", Messages.getQuestionIcon()); 311 | if (confirm == 2) { 312 | return; 313 | } 314 | } else { 315 | int confirm = Messages.showOkCancelDialog(project, "Confirm generate mybatis code?", "Mybatis Generator Plus", Messages.getQuestionIcon()); 316 | if (confirm == 2) { 317 | return; 318 | } 319 | } 320 | 321 | super.doOKAction(); 322 | 323 | this.generate(connectionConfig); 324 | 325 | } 326 | 327 | private boolean testConnection(RawConnectionConfig connectionConfig, Credential credential) { 328 | String url = connectionConfig.getUrl(); 329 | CredentialAttributes credentialAttributes = new CredentialAttributes(PluginContants.PLUGIN_NAME + "-" + url, credential.getUsername(), this.getClass(), false); 330 | String password = PasswordSafe.getInstance().getPassword(credentialAttributes); 331 | try { 332 | DatabaseUtils.testConnection(connectionConfig.getDriverClass(), connectionConfig.getUrl(), credential.getUsername(), password, mysql8Box.getSelectedObjects() != null); 333 | return true; 334 | } catch (ClassNotFoundException e) { 335 | Messages.showMessageDialog(project, "Failed to connect to database \n " + e.getMessage(), "Mybatis Generator Plus", Messages.getErrorIcon()); 336 | e.printStackTrace(); 337 | return false; 338 | } catch (SQLException e) { 339 | Messages.showMessageDialog(project, "Failed to connect to database \n " + e.getMessage(), "Mybatis Generator Plus", Messages.getErrorIcon()); 340 | if (e.getErrorCode() == 1045) { 341 | boolean result = getDatabaseCredential(connectionConfig); 342 | if (result) { 343 | Map credentials = myBatisGeneratorConfiguration.getCredentials(); 344 | return testConnection(connectionConfig, credentials.get(connectionConfig.getUrl())); 345 | } else { 346 | return false; 347 | } 348 | } else { 349 | return false; 350 | } 351 | } 352 | } 353 | 354 | private boolean getDatabaseCredential(RawConnectionConfig connectionConfig) { 355 | DatabaseCredentialUI databaseCredentialUI = new DatabaseCredentialUI(anActionEvent.getProject(), connectionConfig.getUrl()); 356 | return databaseCredentialUI.showAndGet(); 357 | } 358 | 359 | private void initOptionsPanel() { 360 | JBPanel optionsPanel = new JBPanel(new GridLayout(8, 4, 10, 10)); 361 | optionsPanel.add(offsetLimitBox); 362 | optionsPanel.add(commentBox); 363 | optionsPanel.add(overrideBox); 364 | optionsPanel.add(needToStringHashcodeEqualsBox); 365 | optionsPanel.add(useSchemaPrefixBox); 366 | optionsPanel.add(needForUpdateBox); 367 | optionsPanel.add(annotationDAOBox); 368 | optionsPanel.add(useDAOExtendStyleBox); 369 | optionsPanel.add(jsr310SupportBox); 370 | optionsPanel.add(annotationBox); 371 | optionsPanel.add(useActualColumnNamesBox); 372 | optionsPanel.add(useTableNameAliasBox); 373 | optionsPanel.add(useExampleBox); 374 | optionsPanel.add(mysql8Box); 375 | optionsPanel.add(lombokAnnotationBox); 376 | optionsPanel.add(lombokBuilderAnnotationBox); 377 | optionsPanel.add(swaggerAnnotationBox); 378 | 379 | useExampleBox.addChangeListener(e -> { 380 | exampleNamePanel.setVisible(useExampleBox.getSelectedObjects() != null); 381 | examplePackagePanel.setVisible(useExampleBox.getSelectedObjects() != null); 382 | }); 383 | 384 | offsetLimitBox.setSelected(tableConfig.isOffsetLimit()); 385 | commentBox.setSelected(tableConfig.isComment()); 386 | overrideBox.setSelected(tableConfig.isOverride()); 387 | needToStringHashcodeEqualsBox.setSelected(tableConfig.isNeedToStringHashcodeEquals()); 388 | useSchemaPrefixBox.setSelected(tableConfig.isUseSchemaPrefix()); 389 | needForUpdateBox.setSelected(tableConfig.isNeedForUpdate()); 390 | annotationDAOBox.setSelected(tableConfig.isAnnotationDAO()); 391 | useDAOExtendStyleBox.setSelected(tableConfig.isUseDAOExtendStyle()); 392 | jsr310SupportBox.setSelected(tableConfig.isJsr310Support()); 393 | annotationBox.setSelected(tableConfig.isAnnotation()); 394 | useActualColumnNamesBox.setSelected(tableConfig.isUseActualColumnNames()); 395 | useTableNameAliasBox.setSelected(tableConfig.isUseTableNameAlias()); 396 | useExampleBox.setSelected(tableConfig.isUseExample()); 397 | mysql8Box.setSelected(tableConfig.isMysql8()); 398 | lombokAnnotationBox.setSelected(tableConfig.isLombokAnnotation()); 399 | lombokBuilderAnnotationBox.setSelected(tableConfig.isLombokBuilderAnnotation()); 400 | swaggerAnnotationBox.setSelected(tableConfig.isSwaggerAnnotation()); 401 | optionsPanel.setName("Options"); 402 | tabpanel.add(optionsPanel); 403 | } 404 | 405 | /** 406 | * 初始化Package组件 407 | */ 408 | private void initHeader(String tableName, String primaryKey) { 409 | JPanel headerPanel = new JBPanel<>(); 410 | headerPanel.setBorder(JBUI.Borders.empty(0, 5)); 411 | VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP); 412 | layout.setVgap(0); 413 | headerPanel.setLayout(layout); 414 | JPanel moduleRootPanel = new JPanel(); 415 | moduleRootPanel.setLayout(new BoxLayout(moduleRootPanel, BoxLayout.X_AXIS)); 416 | JBLabel projectRootLabel = new JBLabel("Module Root:"); 417 | projectRootLabel.setPreferredSize(new Dimension(150, 10)); 418 | moduleRootField.addBrowseFolderListener(new TextBrowseFolderListener(FileChooserDescriptorFactory.createSingleFolderDescriptor()) { 419 | @Override 420 | public void actionPerformed(ActionEvent e) { 421 | super.actionPerformed(e); 422 | moduleRootField.setText(moduleRootField.getText().replaceAll("\\\\", "/")); 423 | } 424 | }); 425 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getModuleRootPath())) { 426 | moduleRootField.setText(tableConfig.getModuleRootPath()); 427 | } else { 428 | moduleRootField.setText(project.getBasePath()); 429 | } 430 | moduleRootPanel.add(projectRootLabel); 431 | moduleRootPanel.add(moduleRootField); 432 | 433 | //Table 434 | JPanel tableNamePanel = new JPanel(); 435 | tableNamePanel.setLayout(new BoxLayout(tableNamePanel, BoxLayout.X_AXIS)); 436 | JLabel tableLabel = new JLabel("Table Name:"); 437 | tableLabel.setLabelFor(tableNameField); 438 | tableLabel.setPreferredSize(new Dimension(150, 10)); 439 | tableNamePanel.add(tableLabel); 440 | tableNamePanel.add(tableNameField); 441 | 442 | if (psiElements.length > 1) { 443 | tableNameField.addFocusListener(new JTextFieldHintListener(tableNameField, "eg:db_table")); 444 | } else { 445 | tableNameField.setText(tableName); 446 | } 447 | tableNameField.setEditable(false); 448 | tableNameField.addKeyListener(new KeyAdapter() { 449 | @Override 450 | public void keyReleased(KeyEvent e) { 451 | String entityName = StringUtils.dbStringToCamelStyle(tableNameField.getText()); 452 | domainNameField.setText(entityName); 453 | mapperNameField.setText(getMapperName(entityName)); 454 | exampleNameField.setText(getExampleName(entityName)); 455 | } 456 | }); 457 | 458 | JPanel primaryPanel = new JPanel(); 459 | primaryPanel.setLayout(new BoxLayout(primaryPanel, BoxLayout.X_AXIS)); 460 | JLabel primaryKeyLabel = new JLabel(" Primary Key:"); 461 | primaryKeyLabel.setLabelFor(primaryKeyField); 462 | primaryKeyLabel.setPreferredSize(new Dimension(150, 10)); 463 | tableNamePanel.add(primaryKeyLabel); 464 | tableNamePanel.add(primaryKeyField); 465 | 466 | primaryKeyField.setText(primaryKey); 467 | primaryKeyField.setEditable(false); 468 | headerPanel.add(moduleRootPanel); 469 | headerPanel.add(tableNamePanel); 470 | headerPanel.add(primaryPanel); 471 | contentPane.add(headerPanel); 472 | } 473 | 474 | private void initGeneralPanel(String modelName) { 475 | JPanel domainNamePanel = new JPanel(); 476 | domainNamePanel.setLayout(new BoxLayout(domainNamePanel, BoxLayout.X_AXIS)); 477 | JLabel entityNameLabel = new JLabel("Domain Name:"); 478 | entityNameLabel.setPreferredSize(new Dimension(150, 10)); 479 | domainNamePanel.add(entityNameLabel); 480 | domainNamePanel.add(domainNameField); 481 | if (psiElements.length > 1) { 482 | domainNameField.addFocusListener(new JTextFieldHintListener(domainNameField, "eg:DbTable")); 483 | } else { 484 | domainNameField.setText(modelName); 485 | } 486 | domainNameField.addKeyListener(new KeyAdapter() { 487 | @Override 488 | public void keyReleased(KeyEvent e) { 489 | mapperNameField.setText(getMapperName(domainNameField.getText())); 490 | exampleNameField.setText(getExampleName(domainNameField.getText())); 491 | } 492 | }); 493 | 494 | //MapperName 495 | JPanel mapperNamePanel = new JPanel(); 496 | mapperNamePanel.setLayout(new BoxLayout(mapperNamePanel, BoxLayout.X_AXIS)); 497 | JLabel mapperNameLabel = new JLabel("Mapper Name:"); 498 | mapperNameLabel.setPreferredSize(new Dimension(150, 10)); 499 | mapperNameLabel.setLabelFor(domainNameField); 500 | mapperNamePanel.add(mapperNameLabel); 501 | mapperNamePanel.add(mapperNameField); 502 | if (psiElements.length > 1) { 503 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getMapperPostfix())) { 504 | mapperNameField.addFocusListener(new JTextFieldHintListener(mapperNameField, "eg:DbTable" + tableConfig.getMapperPostfix())); 505 | } else { 506 | mapperNameField.addFocusListener(new JTextFieldHintListener(mapperNameField, "eg:DbTable" + "Mapper")); 507 | } 508 | } else { 509 | mapperNameField.setText(getMapperName(modelName)); 510 | } 511 | 512 | exampleNamePanel.setLayout(new BoxLayout(exampleNamePanel, BoxLayout.X_AXIS)); 513 | JLabel exampleNameLabel = new JLabel("Example Name:"); 514 | exampleNameLabel.setPreferredSize(new Dimension(150, 10)); 515 | exampleNameLabel.setLabelFor(domainNameField); 516 | exampleNamePanel.add(exampleNameLabel); 517 | exampleNamePanel.add(exampleNameField); 518 | if (psiElements.length > 1) { 519 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getExamplePostfix())) { 520 | exampleNameField.addFocusListener(new JTextFieldHintListener(exampleNameField, "eg:DbTable" + tableConfig.getExamplePostfix())); 521 | } else { 522 | exampleNameField.addFocusListener(new JTextFieldHintListener(exampleNameField, "eg:DbTable" + "Example")); 523 | } 524 | } else { 525 | exampleNameField.setText(getExampleName(modelName)); 526 | } 527 | 528 | exampleNamePanel.setVisible(tableConfig.isUseExample()); 529 | 530 | 531 | JPanel basePackagePanel = new JPanel(); 532 | basePackagePanel.setLayout(new BoxLayout(basePackagePanel, BoxLayout.X_AXIS)); 533 | JBLabel basePackageLabel = new JBLabel("Base Package:"); 534 | basePackageLabel.setPreferredSize(new Dimension(150, 10)); 535 | basePackageField = new EditorTextFieldWithBrowseButton(project, false); 536 | basePackageField.addActionListener(e -> { 537 | final PackageChooserDialog chooser = new PackageChooserDialog("Select Base Package", project); 538 | chooser.selectPackage(basePackageField.getText()); 539 | chooser.show(); 540 | final PsiPackage psiPackage = chooser.getSelectedPackage(); 541 | String packageName = psiPackage == null ? null : psiPackage.getQualifiedName(); 542 | if (!StringUtils.isEmpty(packageName)) { 543 | basePackageField.setText(packageName); 544 | domainPackageField.setText(packageName + ".domain"); 545 | mapperPackageField.setText(packageName + "." + getMapperPostfix().toLowerCase()); 546 | examplePackageField.setText(packageName + "." + getExamplePostfix().toLowerCase()); 547 | } 548 | }); 549 | basePackageField.addKeyListener(new KeyAdapter() { 550 | @Override 551 | public void keyReleased(KeyEvent e) { 552 | domainPackageField.setText(basePackageField.getText() + ".domain"); 553 | mapperPackageField.setText(basePackageField.getText() + "." + getMapperPostfix().toLowerCase()); 554 | examplePackageField.setText(basePackageField.getText() + "." + getExamplePostfix().toLowerCase()); 555 | } 556 | }); 557 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getBasePackage())) { 558 | basePackageField.setText(tableConfig.getBasePackage()); 559 | } else { 560 | basePackageField.setText(""); 561 | } 562 | basePackagePanel.add(basePackageLabel); 563 | basePackagePanel.add(basePackageField); 564 | 565 | this.domainPackageField = new EditorTextFieldWithBrowseButton(project, false); 566 | 567 | 568 | JPanel entityPackagePanel = new JPanel(); 569 | entityPackagePanel.setLayout(new BoxLayout(entityPackagePanel, BoxLayout.X_AXIS)); 570 | JBLabel entityPackageLabel = new JBLabel("Domain Package:"); 571 | entityPackageLabel.setPreferredSize(new Dimension(150, 10)); 572 | domainPackageField.addActionListener(e -> { 573 | final PackageChooserDialog chooser = new PackageChooserDialog("Select Entity Package", project); 574 | chooser.selectPackage(domainPackageField.getText()); 575 | chooser.show(); 576 | final PsiPackage psiPackage = chooser.getSelectedPackage(); 577 | String packageName = psiPackage == null ? null : psiPackage.getQualifiedName(); 578 | if (!StringUtils.isEmpty(packageName)) { 579 | domainPackageField.setText(packageName); 580 | } 581 | }); 582 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getDomainPackage())) { 583 | domainPackageField.setText(tableConfig.getDomainPackage()); 584 | } else { 585 | domainPackageField.setText(""); 586 | } 587 | entityPackagePanel.add(entityPackageLabel); 588 | entityPackagePanel.add(domainPackageField); 589 | 590 | JPanel mapperPackagePanel = new JPanel(); 591 | mapperPackagePanel.setLayout(new BoxLayout(mapperPackagePanel, BoxLayout.X_AXIS)); 592 | JLabel mapperPackageLabel = new JLabel("Mapper Package:"); 593 | mapperPackageLabel.setPreferredSize(new Dimension(150, 10)); 594 | mapperPackageField = new EditorTextFieldWithBrowseButton(project, false); 595 | mapperPackageField.addActionListener(event -> { 596 | final PackageChooserDialog packageChooserDialog = new PackageChooserDialog("Select Mapper Package", project); 597 | packageChooserDialog.selectPackage(mapperPackageField.getText()); 598 | packageChooserDialog.show(); 599 | 600 | final PsiPackage psiPackage = packageChooserDialog.getSelectedPackage(); 601 | String packageName = psiPackage == null ? null : psiPackage.getQualifiedName(); 602 | if (!StringUtils.isEmpty(packageName)) { 603 | mapperPackageField.setText(packageName); 604 | } 605 | }); 606 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getMapperPackage())) { 607 | mapperPackageField.setText(tableConfig.getMapperPackage()); 608 | } else { 609 | mapperPackageField.setText(""); 610 | } 611 | mapperPackagePanel.add(mapperPackageLabel); 612 | mapperPackagePanel.add(mapperPackageField); 613 | 614 | examplePackagePanel.setLayout(new BoxLayout(examplePackagePanel, BoxLayout.X_AXIS)); 615 | 616 | examplePackageField = new EditorTextFieldWithBrowseButton(project, false); 617 | examplePackageField.addActionListener(e -> { 618 | final PackageChooserDialog packageChooserDialog = new PackageChooserDialog("Select Example Package", project); 619 | packageChooserDialog.selectPackage(examplePackageField.getText()); 620 | packageChooserDialog.show(); 621 | 622 | final PsiPackage psiPackage = packageChooserDialog.getSelectedPackage(); 623 | String packageName = psiPackage == null ? null : psiPackage.getQualifiedName(); 624 | if (!StringUtils.isEmpty(packageName)) { 625 | examplePackageField.setText(packageName); 626 | } 627 | }); 628 | 629 | JLabel examplePackageLabel = new JLabel("Example Package:"); 630 | examplePackageLabel.setPreferredSize(new Dimension(150, 10)); 631 | examplePackageField.setText(tableConfig.getExamplePackage()); 632 | examplePackagePanel.add(examplePackageLabel); 633 | examplePackagePanel.add(examplePackageField); 634 | examplePackagePanel.setVisible(tableConfig.isUseExample()); 635 | 636 | JPanel xmlPackagePanel = new JPanel(); 637 | xmlPackagePanel.setLayout(new BoxLayout(xmlPackagePanel, BoxLayout.X_AXIS)); 638 | JLabel xmlPackageLabel = new JLabel("Xml Package:"); 639 | xmlPackageLabel.setPreferredSize(new Dimension(150, 10)); 640 | xmlPackageField.setText(tableConfig.getXmlPackage()); 641 | xmlPackagePanel.add(xmlPackageLabel); 642 | xmlPackagePanel.add(xmlPackageField); 643 | 644 | JPanel generalPanel = new JPanel(); 645 | generalPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 646 | generalPanel.add(new TitledSeparator("Domain")); 647 | 648 | JPanel domainPanel = new JPanel(); 649 | domainPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 650 | 651 | domainPanel.add(domainNamePanel); 652 | domainPanel.add(mapperNamePanel); 653 | domainPanel.add(exampleNamePanel); 654 | generalPanel.add(domainPanel); 655 | 656 | generalPanel.add(new TitledSeparator("Package")); 657 | 658 | JPanel packagePanel = new JPanel(); 659 | packagePanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP)); 660 | 661 | packagePanel.add(basePackagePanel); 662 | packagePanel.add(entityPackagePanel); 663 | packagePanel.add(mapperPackagePanel); 664 | packagePanel.add(examplePackagePanel); 665 | packagePanel.add(xmlPackagePanel); 666 | generalPanel.add(packagePanel); 667 | generalPanel.setName("General"); 668 | tabpanel.add(generalPanel); 669 | } 670 | 671 | public void generate(RawConnectionConfig connectionConfig) { 672 | tableConfig.setName(tableNameField.getText()); 673 | tableConfig.setTableName(tableNameField.getText()); 674 | tableConfig.setModuleRootPath(moduleRootField.getText()); 675 | 676 | tableConfig.setBasePackage(basePackageField.getText()); 677 | tableConfig.setDomainPackage(domainPackageField.getText()); 678 | tableConfig.setMapperPackage(mapperPackageField.getText()); 679 | tableConfig.setExamplePackage(examplePackageField.getText()); 680 | tableConfig.setXmlPackage(xmlPackageField.getText()); 681 | 682 | tableConfig.setMapperName(mapperNameField.getText()); 683 | tableConfig.setDomainName(domainNameField.getText()); 684 | tableConfig.setPrimaryKey(primaryKeyField.getText()); 685 | tableConfig.setExampleName(exampleNameField.getText()); 686 | 687 | tableConfig.setOffsetLimit(offsetLimitBox.getSelectedObjects() != null); 688 | tableConfig.setComment(commentBox.getSelectedObjects() != null); 689 | tableConfig.setOverride(overrideBox.getSelectedObjects() != null); 690 | tableConfig.setNeedToStringHashcodeEquals(needToStringHashcodeEqualsBox.getSelectedObjects() != null); 691 | tableConfig.setUseSchemaPrefix(useSchemaPrefixBox.getSelectedObjects() != null); 692 | tableConfig.setNeedForUpdate(needForUpdateBox.getSelectedObjects() != null); 693 | tableConfig.setAnnotationDAO(annotationDAOBox.getSelectedObjects() != null); 694 | tableConfig.setUseDAOExtendStyle(useDAOExtendStyleBox.getSelectedObjects() != null); 695 | tableConfig.setJsr310Support(jsr310SupportBox.getSelectedObjects() != null); 696 | tableConfig.setAnnotation(annotationBox.getSelectedObjects() != null); 697 | tableConfig.setUseActualColumnNames(useActualColumnNamesBox.getSelectedObjects() != null); 698 | tableConfig.setUseTableNameAlias(useTableNameAliasBox.getSelectedObjects() != null); 699 | tableConfig.setUseExample(useExampleBox.getSelectedObjects() != null); 700 | tableConfig.setMysql8(mysql8Box.getSelectedObjects() != null); 701 | tableConfig.setLombokAnnotation(lombokAnnotationBox.getSelectedObjects() != null); 702 | tableConfig.setLombokBuilderAnnotation(lombokBuilderAnnotationBox.getSelectedObjects() != null); 703 | tableConfig.setSwaggerAnnotation(swaggerAnnotationBox.getSelectedObjects() != null); 704 | tableConfig.setSourcePath(this.tableConfig.getSourcePath()); 705 | tableConfig.setResourcePath(this.tableConfig.getResourcePath()); 706 | 707 | new MyBatisGenerateCommand(tableConfig).execute(project, connectionConfig); 708 | 709 | } 710 | 711 | private String getMapperName(String entityName) { 712 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getMapperPostfix())) { 713 | return entityName + tableConfig.getMapperPostfix(); 714 | } else { 715 | return (entityName + "Mapper"); 716 | } 717 | } 718 | 719 | private String getMapperPostfix() { 720 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getMapperPostfix())) { 721 | return tableConfig.getMapperPostfix(); 722 | } else { 723 | return "Mapper"; 724 | } 725 | } 726 | 727 | private String getExamplePostfix() { 728 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getExamplePostfix())) { 729 | return tableConfig.getExamplePostfix(); 730 | } else { 731 | return "Example"; 732 | } 733 | } 734 | 735 | private String getExampleName(String entityName) { 736 | if (tableConfig != null && !StringUtils.isEmpty(tableConfig.getExamplePostfix())) { 737 | return entityName + tableConfig.getExamplePostfix(); 738 | } else { 739 | return (entityName + "Example"); 740 | } 741 | } 742 | 743 | @Nullable 744 | @Override 745 | protected JComponent createCenterPanel() { 746 | return contentPane; 747 | } 748 | } 749 | --------------------------------------------------------------------------------