Full Code of zouzg/mybatis-generator-gui for AI

master dde137711ac1 cached
55 files
199.5 KB
47.5k tokens
342 symbols
1 requests
Download .txt
Showing preview only (216K chars total). Download the full file or copy to clipboard to get everything.
Repository: zouzg/mybatis-generator-gui
Branch: master
Commit: dde137711ac1
Files: 55
Total size: 199.5 KB

Directory structure:
gitextract_tz7ayfc4/

├── .gitignore
├── README.md
├── _config.yml
├── package/
│   └── macosx/
│       └── mybatis-generator-gui.icns
├── pom.xml
└── src/
    ├── main/
    │   ├── java/
    │   │   └── com/
    │   │       └── zzg/
    │   │           └── mybatis/
    │   │               └── generator/
    │   │                   ├── Main.java
    │   │                   ├── MainUI.java
    │   │                   ├── bridge/
    │   │                   │   └── MybatisGeneratorBridge.java
    │   │                   ├── controller/
    │   │                   │   ├── BaseFXController.java
    │   │                   │   ├── DbConnectionController.java
    │   │                   │   ├── FXMLPage.java
    │   │                   │   ├── GeneratorConfigController.java
    │   │                   │   ├── MainUIController.java
    │   │                   │   ├── OverSshController.java
    │   │                   │   ├── PictureProcessStateController.java
    │   │                   │   ├── SelectTableColumnController.java
    │   │                   │   ├── TabPaneController.java
    │   │                   │   └── TableColumnConfigsController.java
    │   │                   ├── exception/
    │   │                   │   └── DbDriverLoadingException.java
    │   │                   ├── model/
    │   │                   │   ├── CachedFXMLLoader.java
    │   │                   │   ├── DatabaseConfig.java
    │   │                   │   ├── DatabaseDTO.java
    │   │                   │   ├── DbType.java
    │   │                   │   ├── GeneratorConfig.java
    │   │                   │   └── UITableColumnVO.java
    │   │                   ├── plugins/
    │   │                   │   ├── CommonDAOInterfacePlugin.java
    │   │                   │   ├── DbRemarksCommentGenerator.java
    │   │                   │   ├── JavaTypeResolverJsr310Impl.java
    │   │                   │   ├── MySQLForUpdatePlugin.java
    │   │                   │   ├── MySQLLimitPlugin.java
    │   │                   │   └── RepositoryPlugin.java
    │   │                   ├── util/
    │   │                   │   ├── ConfigHelper.java
    │   │                   │   ├── ConnectionManager.java
    │   │                   │   ├── DbUtil.java
    │   │                   │   └── MyStringUtils.java
    │   │                   └── view/
    │   │                       ├── AlertUtil.java
    │   │                       ├── LeftDbTreeCell.java
    │   │                       └── UIProgressCallback.java
    │   └── resources/
    │       ├── fxml/
    │       │   ├── MainUI.fxml
    │       │   ├── basicConnection.fxml
    │       │   ├── generatorConfigs.fxml
    │       │   ├── newConnection.fxml
    │       │   ├── selectTableColumn.fxml
    │       │   ├── sshBasedConnection.fxml
    │       │   └── tableColumnConfigs.fxml
    │       ├── lib/
    │       │   ├── mysql-connector-java-5.1.38.jar
    │       │   ├── mysql-connector-java-8.0.11.jar
    │       │   ├── ojdbc6.jar
    │       │   ├── postgresql-9.4.1209.jar
    │       │   ├── sqlite-jdbc-3.19.3.jar
    │       │   └── sqljdbc4-4.0.jar
    │       ├── logback.xml
    │       └── style.css
    └── test/
        └── java/
            └── com/
                └── zzg/
                    └── mybatis/
                        └── generator/
                            └── util/
                                ├── ConfigHelperTest.java
                                └── StringUtilTest.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
/target/
/config/
.idea
.settings
logs
*.iml
.project
.classpath
/src/main/resources/sqlite3.db
/config/


================================================
FILE: README.md
================================================
mybatis-generator-gui
==============

mybatis-generator-gui是基于 [mybatis generator](http://www.mybatis.org/generator/index.html) 开发一款界面工具, 本工具可以使你非常容易及快速生成Mybatis的Java POJO文件及数据库Mapping文件。

![image](https://user-images.githubusercontent.com/3505708/49334784-1a42c980-f619-11e8-914d-9ea85db9cec3.png)


![basic](https://user-images.githubusercontent.com/3505708/51911610-45754980-240d-11e9-85ad-643e55cafab2.png)


![overSSH](https://user-images.githubusercontent.com/3505708/51911646-5920b000-240d-11e9-9048-738306a56d14.png)

![SearchSupport](https://user-images.githubusercontent.com/8142133/115959972-881d2200-a541-11eb-8ad4-052f379b91f1.png)


### 核心特性
* 按照界面步骤轻松生成代码,省去XML繁琐的学习与配置过程
* 保存数据库连接与Generator配置,每次代码生成轻松搞定
* 内置常用插件,比如分页插件
* 支持OverSSH 方式,通过SSH隧道连接至公司内网访问数据库
* 把数据库中表列的注释生成为Java实体的注释,生成的实体清晰明了
* 可选的去除掉对版本管理不友好的注释,这样新增或删除字段重新生成的文件比较过来清楚
* 目前已经支持Mysql、Mysql8、Oracle、PostgreSQL与SQL Server,暂不对其他非主流数据库提供支持。(MySQL支持的比较好,其他数据库有什么问题可以在issue中反馈)

### 运行要求(重要!!!)
本工具仅支持Java的2个最新的LTS版本,jdk8和jdk11
* jdk1.8要求版本在<strong>1.8.0.60</strong>以上版本
* Java 11无版本要求

### 直接运行(非必须)
推荐使用IDE直接运行,如果需要二进制安装包,可以关注公众号获取二进制安装版,目前支持Windows和MacOS,注意你的JDK是不是1.8,并且版本大于1.8.0.60


### 启动本软件

* 方法一:关注微信公众号“搬砖头也要有态度”,回复“GUI”获取下载链接
    
  ![image](https://user-images.githubusercontent.com/3505708/61360019-2893dc00-a8b0-11e9-8dc9-a020e997ab87.png)

* 方法二: 自助构建

  ```bash
  git clone https://github.com/zouzg/mybatis-generator-gui
  cd mybatis-generator-gui
  mvn jfx:jar
  cd target/jfx/app/
  java -jar mybatis-generator-gui.jar
  ```

* 方法三: IDE中运行

  Eclipse or IntelliJ IDEA中启动, 找到`com.zzg.mybatis.generator.MainUI`类并运行就可以了(主要你的IED运行的jdk版本是否符合要求)

* 方法四:打包为本地原生应用,双击快捷方式即可启动,方便快捷

  如果不想打包后的安装包logo为Java的灰色的茶杯,需要在pom文件里将对应操作系统平台的图标注释放开

  ```bash
  #<icon>${project.basedir}/package/windows/mybatis-generator-gui.ico</icon>为windows
  #<icon>${project.basedir}/package/macosx/mybatis-generator-gui.icns</icon>为mac
  mvn jfx:native
  ```

  另外需要注意,windows系统打包成exe的话需要安装WiXToolset3+的环境;由于打包后会把jre打入安装包,两个平台均100M左右,体积较大请自行打包;打包后的安装包在target/jfx/native目录下

### 注意事项
* 本自动生成代码工具只适合生成单表的增删改查,对于需要做数据库联合查询的,请自行写新的XML与Mapper;
* 部分系统在中文输入方法时输入框中无法输入文字,请切换成英文输入法;
* 如果不明白对应字段或选项是什么意思的时候,把光标放在对应字段或Label上停留一会然后如果有解释会出现解释;


### 文档
更多详细文档请参考本库的Wiki
* [Usage](https://github.com/astarring/mybatis-generator-gui/wiki/Usage-Guide)


### 贡献
目前本工具只是本人项目人使用到了并且觉得非常有用所以把它开源,如果你觉得有用并且想改进本软件,你可以:
* 对于你认为有用的功能,你可以在Issue提,我可以开发的尽量满足
* 对于有Bug的地方,请按如下方式在Issue中提bug
    * 如何重现你的bug,包括你使用的系统,JDK版本,数据库类型及版本
    * 如果有任何的错误截图会更好
    * 如果你是一些常见的数据库连接、软件启动不了等问题,请先仔细阅读上面的文档,再解决不了在下面的QQ群中问(问问题的时候尽量把各种信息都提供好,否则只是几行文字是没有人愿意为你解答的)。
    
### QQ群
鉴于有的同学可能有一些特殊情况不能使用,我建了一个钉钉群供大家交流,钉钉群号:35412531 (原QQ群已不再提供,QQ不方便打开)

- - -
Licensed under the Apache 2.0 License

Copyright 2017 by Owen Zou


================================================
FILE: _config.yml
================================================
theme: jekyll-theme-cayman

================================================
FILE: pom.xml
================================================
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zzg</groupId>
    <artifactId>mybatis-generator-gui</artifactId>
    <version>0.8.9-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <!-- Java 11请修改此处为11 -->
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.6</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.0</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>[2.7,)</version>
        </dependency>
        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
            <version>3.8.11.2</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>
        <dependency>
            <groupId>com.softwareloop</groupId>
            <artifactId>mybatis-generator-lombok-plugin</artifactId>
            <version>1.0</version>
        </dependency>
        <!-- Java 11请关闭下面注释 -->
        <!--
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>11</version>
        </dependency>
        -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <!-- Java 11请修改此处为11 -->
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.zenjava</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>8.8.3</version>
                <configuration>
                    <bundleArguments>
                        <!-- windows打包开启-->
                        <icon>${project.basedir}/package/windows/mybatis-generator-gui.ico</icon>
                        <!-- mac打包开启-->
                        <icon>${project.basedir}/package/macosx/mybatis-generator-gui.icns</icon>
                    </bundleArguments>
                    <mainClass>com.zzg.mybatis.generator.MainUI</mainClass>
                    <vendor>Owen Zou</vendor>
                    <verbose>false</verbose>
                    <jfxMainAppJarName>mybatis-generator-gui.jar</jfxMainAppJarName>
                    <needShortcut>true</needShortcut>
                    <needMenu>true</needMenu>
                    <copyAdditionalAppResourcesToJar>true</copyAdditionalAppResourcesToJar>
                    <additionalAppResources>${project.basedir}/src/main/resources</additionalAppResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

================================================
FILE: src/main/java/com/zzg/mybatis/generator/Main.java
================================================
package com.zzg.mybatis.generator;

import javafx.application.Application;

/**
 * @author 欧闻
 * @version $Id: Main, v 0.1 2021/4/20 欧闻 Exp $$
 */
public class Main {

    public static void main(String[] args) {
        Application.launch(MainUI.class);
    }

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/MainUI.java
================================================
package com.zzg.mybatis.generator;

import com.zzg.mybatis.generator.controller.MainUIController;
import com.zzg.mybatis.generator.util.ConfigHelper;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.net.URL;

/**
 * 这是本软件的主入口,要运行本软件请直接运行本类就可以了,不用传入任何参数
 * 本软件要求jkd版本大于1.8.0.40
 */
public class MainUI extends Application {

	private static final Logger _LOG = LoggerFactory.getLogger(MainUI.class);

	@Override
	public void start(Stage primaryStage) throws Exception {
		ConfigHelper.createEmptyFiles();
		URL url = Thread.currentThread().getContextClassLoader().getResource("fxml/MainUI.fxml");
		FXMLLoader fxmlLoader = new FXMLLoader(url);
		Parent root = fxmlLoader.load();
		primaryStage.setResizable(true);
		primaryStage.setScene(new Scene(root));
		primaryStage.setTitle("Mybatis Generator GUI");
		Image imageIcon = new Image("icons/mybatis-logo.png");
		primaryStage.getIcons().add(imageIcon);
		primaryStage.show();

		MainUIController controller = fxmlLoader.getController();
		controller.setPrimaryStage(primaryStage);
	}

	public static void main(String[] args) {
		launch(args);
	}

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/bridge/MybatisGeneratorBridge.java
================================================
package com.zzg.mybatis.generator.bridge;

import com.jcraft.jsch.Session;
import com.zzg.mybatis.generator.controller.PictureProcessStateController;
import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.model.DbType;
import com.zzg.mybatis.generator.model.GeneratorConfig;
import com.zzg.mybatis.generator.plugins.DbRemarksCommentGenerator;
import com.zzg.mybatis.generator.util.ConfigHelper;
import com.zzg.mybatis.generator.util.DbUtil;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.api.ProgressCallback;
import org.mybatis.generator.api.ShellCallback;
import org.mybatis.generator.config.*;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The bridge between GUI and the mybatis generator. All the operation to  mybatis generator should proceed through this
 * class
 * <p>
 * Created by Owen on 6/30/16.
 */
public class MybatisGeneratorBridge {

	private static final Logger _LOG = LoggerFactory.getLogger(MybatisGeneratorBridge.class);

    private GeneratorConfig generatorConfig;

    private DatabaseConfig selectedDatabaseConfig;

    private ProgressCallback progressCallback;

    private List<IgnoredColumn> ignoredColumns;

    private List<ColumnOverride> columnOverrides;

    public MybatisGeneratorBridge() {
    }

    public void setGeneratorConfig(GeneratorConfig generatorConfig) {
        this.generatorConfig = generatorConfig;
    }

    public void setDatabaseConfig(DatabaseConfig databaseConfig) {
        this.selectedDatabaseConfig = databaseConfig;
    }

    public void generate() throws Exception {
        Configuration configuration = new Configuration();
        Context context = new Context(ModelType.CONDITIONAL);
        configuration.addContext(context);
		
        context.addProperty("javaFileEncoding", "UTF-8");
        
		String dbType = selectedDatabaseConfig.getDbType();
		String connectorLibPath = ConfigHelper.findConnectorLibPath(dbType);
	    _LOG.info("connectorLibPath: {}", connectorLibPath);
	    configuration.addClasspathEntry(connectorLibPath);
        // Table configuration
        TableConfiguration tableConfig = new TableConfiguration(context);
        tableConfig.setTableName(generatorConfig.getTableName());
        tableConfig.setDomainObjectName(generatorConfig.getDomainObjectName());
        if(!generatorConfig.isUseExample()) {
            tableConfig.setUpdateByExampleStatementEnabled(false);
            tableConfig.setCountByExampleStatementEnabled(false);
            tableConfig.setDeleteByExampleStatementEnabled(false);
            tableConfig.setSelectByExampleStatementEnabled(false);
        }

		context.addProperty("autoDelimitKeywords", "true");
		if (DbType.MySQL.name().equals(dbType) || DbType.MySQL_8.name().equals(dbType)) {
			tableConfig.setSchema(selectedDatabaseConfig.getSchema());
			// 由于beginningDelimiter和endingDelimiter的默认值为双引号("),在Mysql中不能这么写,所以还要将这两个默认值改为`
			context.addProperty("beginningDelimiter", "`");
			context.addProperty("endingDelimiter", "`");
		} else {
            tableConfig.setCatalog(selectedDatabaseConfig.getSchema());
	    }
        if (generatorConfig.isUseSchemaPrefix()) {
            if (DbType.MySQL.name().equals(dbType) || DbType.MySQL_8.name().equals(dbType)) {
                tableConfig.setSchema(selectedDatabaseConfig.getSchema());
            } else if (DbType.Oracle.name().equals(dbType)) {
                //Oracle的schema为用户名,如果连接用户拥有dba等高级权限,若不设schema,会导致把其他用户下同名的表也生成一遍导致mapper中代码重复
                tableConfig.setSchema(selectedDatabaseConfig.getUsername());
            } else {
                tableConfig.setCatalog(selectedDatabaseConfig.getSchema());
            }
        }
        // 针对 postgresql 单独配置
		if (DbType.PostgreSQL.name().equals(dbType)) {
            tableConfig.setDelimitIdentifiers(true);
        }

        //添加GeneratedKey主键生成
		if (StringUtils.isNotEmpty(generatorConfig.getGenerateKeys())) {
            String dbType2 = dbType;
            if (DbType.MySQL.name().equals(dbType2) || DbType.MySQL_8.name().equals(dbType)) {
                dbType2 = "JDBC";
                //dbType为JDBC,且配置中开启useGeneratedKeys时,Mybatis会使用Jdbc3KeyGenerator,
                //使用该KeyGenerator的好处就是直接在一次INSERT 语句内,通过resultSet获取得到 生成的主键值,
                //并很好的支持设置了读写分离代理的数据库
                //例如阿里云RDS + 读写分离代理
                //无需指定主库
                //当使用SelectKey时,Mybatis会使用SelectKeyGenerator,INSERT之后,多发送一次查询语句,获得主键值
                //在上述读写分离被代理的情况下,会得不到正确的主键
            }
			tableConfig.setGeneratedKey(new GeneratedKey(generatorConfig.getGenerateKeys(), dbType2, true, null));
		}

        if (generatorConfig.getMapperName() != null) {
            tableConfig.setMapperName(generatorConfig.getMapperName());
        }
        // add ignore columns
        if (ignoredColumns != null) {
            ignoredColumns.forEach(tableConfig::addIgnoredColumn);
        }
        if (columnOverrides != null) {
            columnOverrides.forEach(tableConfig::addColumnOverride);
        }
        if (generatorConfig.isUseActualColumnNames()) {
			tableConfig.addProperty("useActualColumnNames", "true");
        }

		if(generatorConfig.isUseTableNameAlias()){
            tableConfig.setAlias(generatorConfig.getTableName());
        }

        JDBCConnectionConfiguration jdbcConfig = new JDBCConnectionConfiguration();
        if (DbType.MySQL.name().equals(dbType) || DbType.MySQL_8.name().equals(dbType)) {
	        jdbcConfig.addProperty("nullCatalogMeansCurrent", "true");
	        // useInformationSchema可以拿到表注释,从而生成类注释可以使用表的注释
	        jdbcConfig.addProperty("useInformationSchema", "true");
        }
        jdbcConfig.setDriverClass(DbType.valueOf(dbType).getDriverClass());
        jdbcConfig.setConnectionURL(DbUtil.getConnectionUrlWithSchema(selectedDatabaseConfig));
        jdbcConfig.setUserId(selectedDatabaseConfig.getUsername());
        jdbcConfig.setPassword(selectedDatabaseConfig.getPassword());
        if(DbType.Oracle.name().equals(dbType)){
            jdbcConfig.getProperties().setProperty("remarksReporting", "true");
        }
        // java model
        JavaModelGeneratorConfiguration modelConfig = new JavaModelGeneratorConfiguration();
        modelConfig.setTargetPackage(generatorConfig.getModelPackage());
        modelConfig.setTargetProject(generatorConfig.getProjectFolder() + "/" + generatorConfig.getModelPackageTargetFolder());
        // Mapper configuration
        SqlMapGeneratorConfiguration mapperConfig = new SqlMapGeneratorConfiguration();
        mapperConfig.setTargetPackage(generatorConfig.getMappingXMLPackage());
        mapperConfig.setTargetProject(generatorConfig.getProjectFolder() + "/" + generatorConfig.getMappingXMLTargetFolder());
        // DAO
        JavaClientGeneratorConfiguration daoConfig = new JavaClientGeneratorConfiguration();
        daoConfig.setConfigurationType("XMLMAPPER");
        daoConfig.setTargetPackage(generatorConfig.getDaoPackage());
        daoConfig.setTargetProject(generatorConfig.getProjectFolder() + "/" + generatorConfig.getDaoTargetFolder());


        context.setId("myid");
        context.addTableConfiguration(tableConfig);
        context.setJdbcConnectionConfiguration(jdbcConfig);
        context.setJavaModelGeneratorConfiguration(modelConfig);
        context.setSqlMapGeneratorConfiguration(mapperConfig);
        context.setJavaClientGeneratorConfiguration(daoConfig);
        // Comment
        CommentGeneratorConfiguration commentConfig = new CommentGeneratorConfiguration();
        commentConfig.setConfigurationType(DbRemarksCommentGenerator.class.getName());
        if (generatorConfig.isComment()) {
            commentConfig.addProperty("columnRemarks", "true");
        }
        if (generatorConfig.isAnnotation()) {
            commentConfig.addProperty("annotations", "true");
        }
        context.setCommentGeneratorConfiguration(commentConfig);
        // set java file encoding
        context.addProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING, generatorConfig.getEncoding());

        //实体添加序列化
        PluginConfiguration serializablePluginConfiguration = new PluginConfiguration();
        serializablePluginConfiguration.addProperty("type", "org.mybatis.generator.plugins.SerializablePlugin");
        serializablePluginConfiguration.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin");
        context.addPluginConfiguration(serializablePluginConfiguration);

        // Lombok 插件
        if (generatorConfig.isUseLombokPlugin()) {
            PluginConfiguration pluginConfiguration = new PluginConfiguration();
            pluginConfiguration.addProperty("type", "com.softwareloop.mybatis.generator.plugins.LombokPlugin");
            pluginConfiguration.setConfigurationType("com.softwareloop.mybatis.generator.plugins.LombokPlugin");
            context.addPluginConfiguration(pluginConfiguration);
        }
        // toString, hashCode, equals插件
        else if (generatorConfig.isNeedToStringHashcodeEquals()) {
            PluginConfiguration pluginConfiguration1 = new PluginConfiguration();
            pluginConfiguration1.addProperty("type", "org.mybatis.generator.plugins.EqualsHashCodePlugin");
            pluginConfiguration1.setConfigurationType("org.mybatis.generator.plugins.EqualsHashCodePlugin");
            context.addPluginConfiguration(pluginConfiguration1);
            PluginConfiguration pluginConfiguration2 = new PluginConfiguration();
            pluginConfiguration2.addProperty("type", "org.mybatis.generator.plugins.ToStringPlugin");
            pluginConfiguration2.setConfigurationType("org.mybatis.generator.plugins.ToStringPlugin");
            context.addPluginConfiguration(pluginConfiguration2);
        }
        // limit/offset插件
        if (generatorConfig.isOffsetLimit()) {
            if (DbType.MySQL.name().equals(dbType) || DbType.MySQL_8.name().equals(dbType)
		            || DbType.PostgreSQL.name().equals(dbType)) {
                PluginConfiguration pluginConfiguration = new PluginConfiguration();
                pluginConfiguration.addProperty("type", "com.zzg.mybatis.generator.plugins.MySQLLimitPlugin");
                pluginConfiguration.setConfigurationType("com.zzg.mybatis.generator.plugins.MySQLLimitPlugin");
                context.addPluginConfiguration(pluginConfiguration);
            }
        }
        //for JSR310
        if (generatorConfig.isJsr310Support()) {
            JavaTypeResolverConfiguration javaTypeResolverConfiguration = new JavaTypeResolverConfiguration();
            javaTypeResolverConfiguration.setConfigurationType("com.zzg.mybatis.generator.plugins.JavaTypeResolverJsr310Impl");
            context.setJavaTypeResolverConfiguration(javaTypeResolverConfiguration);
        }
        //forUpdate 插件
        if(generatorConfig.isNeedForUpdate()) {
            if (DbType.MySQL.name().equals(dbType)
                    || DbType.PostgreSQL.name().equals(dbType)) {
                PluginConfiguration pluginConfiguration = new PluginConfiguration();
                pluginConfiguration.addProperty("type", "com.zzg.mybatis.generator.plugins.MySQLForUpdatePlugin");
                pluginConfiguration.setConfigurationType("com.zzg.mybatis.generator.plugins.MySQLForUpdatePlugin");
                context.addPluginConfiguration(pluginConfiguration);
            }
        }
        //repository 插件
        if(generatorConfig.isAnnotationDAO()) {
            if (DbType.MySQL.name().equals(dbType) || DbType.MySQL_8.name().equals(dbType)
                    || DbType.PostgreSQL.name().equals(dbType)) {
                PluginConfiguration pluginConfiguration = new PluginConfiguration();
                pluginConfiguration.addProperty("type", "com.zzg.mybatis.generator.plugins.RepositoryPlugin");
                pluginConfiguration.setConfigurationType("com.zzg.mybatis.generator.plugins.RepositoryPlugin");
                context.addPluginConfiguration(pluginConfiguration);
            }
        }
        if (generatorConfig.isUseDAOExtendStyle()) {
            if (DbType.MySQL.name().equals(dbType) || DbType.MySQL_8.name().equals(dbType)
                    || DbType.PostgreSQL.name().equals(dbType)) {
                PluginConfiguration pluginConfiguration = new PluginConfiguration();
				pluginConfiguration.addProperty("useExample", String.valueOf(generatorConfig.isUseExample()));
				pluginConfiguration.addProperty("type", "com.zzg.mybatis.generator.plugins.CommonDAOInterfacePlugin");
                pluginConfiguration.setConfigurationType("com.zzg.mybatis.generator.plugins.CommonDAOInterfacePlugin");
                context.addPluginConfiguration(pluginConfiguration);
            }
        }

        context.setTargetRuntime("MyBatis3");

        List<String> warnings = new ArrayList<>();
        Set<String> fullyqualifiedTables = new HashSet<>();
        Set<String> contexts = new HashSet<>();
        ShellCallback shellCallback = new DefaultShellCallback(true); // override=true
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(configuration, shellCallback, warnings);
        // if overrideXML selected, delete oldXML ang generate new one
		if (generatorConfig.isOverrideXML()) {
			String mappingXMLFilePath = getMappingXMLFilePath(generatorConfig);
			File mappingXMLFile = new File(mappingXMLFilePath);
			if (mappingXMLFile.exists()) {
				mappingXMLFile.delete();
			}
		}
        myBatisGenerator.generate(progressCallback, contexts, fullyqualifiedTables);
    }

    private String getMappingXMLFilePath(GeneratorConfig generatorConfig) {
		StringBuilder sb = new StringBuilder();
		sb.append(generatorConfig.getProjectFolder()).append("/");
		sb.append(generatorConfig.getMappingXMLTargetFolder()).append("/");
		String mappingXMLPackage = generatorConfig.getMappingXMLPackage();
		if (StringUtils.isNotEmpty(mappingXMLPackage)) {
			sb.append(mappingXMLPackage.replace(".", "/")).append("/");
		}
		if (StringUtils.isNotEmpty(generatorConfig.getMapperName())) {
			sb.append(generatorConfig.getMapperName()).append(".xml");
		} else {
			sb.append(generatorConfig.getDomainObjectName()).append("Mapper.xml");
		}

		return sb.toString();
	}

	public void setProgressCallback(ProgressCallback progressCallback) {
        this.progressCallback = progressCallback;
    }

    public void setIgnoredColumns(List<IgnoredColumn> ignoredColumns) {
        this.ignoredColumns = ignoredColumns;
    }

    public void setColumnOverrides(List<ColumnOverride> columnOverrides) {
        this.columnOverrides = columnOverrides;
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/BaseFXController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.zzg.mybatis.generator.view.AlertUtil;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public abstract class BaseFXController implements Initializable {
    private static final Logger _LOG = LoggerFactory.getLogger(BaseFXController.class);

    private Stage primaryStage;
    private Stage dialogStage;

    private static Map<FXMLPage, SoftReference<? extends BaseFXController>> cacheNodeMap = new HashMap<>();

    public BaseFXController loadFXMLPage(String title, FXMLPage fxmlPage, boolean cache) {
        SoftReference<? extends BaseFXController> parentNodeRef = cacheNodeMap.get(fxmlPage);
        if (cache && parentNodeRef != null) {
            return parentNodeRef.get();
        }
        URL skeletonResource = Thread.currentThread().getContextClassLoader().getResource(fxmlPage.getFxml());
        FXMLLoader loader = new FXMLLoader(skeletonResource);
        Parent loginNode;
        try {
            loginNode = loader.load();
            BaseFXController controller     = loader.getController();
            // fix bug: 嵌套弹出时会发生dialogStage被覆盖的情况
            Stage            tmpDialogStage = new Stage();
            tmpDialogStage.setTitle(title);
            tmpDialogStage.initModality(Modality.APPLICATION_MODAL);
            tmpDialogStage.initOwner(getPrimaryStage());
            tmpDialogStage.setScene(new Scene(loginNode));
            tmpDialogStage.setMaximized(false);
            tmpDialogStage.setResizable(false);
            tmpDialogStage.show();
            controller.setDialogStage(tmpDialogStage);
            // put into cache map
            SoftReference<BaseFXController> softReference = new SoftReference<>(controller);
            cacheNodeMap.put(fxmlPage, softReference);

            return controller;
        } catch (IOException e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
        return null;
    }

    public Stage getPrimaryStage() {
        return primaryStage;
    }

    public void setPrimaryStage(Stage primaryStage) {
        this.primaryStage = primaryStage;
    }

    public Stage getDialogStage() {
        return dialogStage;
    }

    public void setDialogStage(Stage dialogStage) {
        this.dialogStage = dialogStage;
    }

    public void showDialogStage() {
        if (dialogStage != null) {
            dialogStage.show();
        }
    }

    public void closeDialogStage() {
        if (dialogStage != null) {
            dialogStage.close();
        }
    }

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/DbConnectionController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.util.ConfigHelper;
import com.zzg.mybatis.generator.view.AlertUtil;
import javafx.fxml.FXML;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextField;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.ResourceBundle;

public class DbConnectionController extends BaseFXController {

    private static final Logger _LOG = LoggerFactory.getLogger(DbConnectionController.class);

    @FXML
    protected TextField nameField;
    @FXML
    protected TextField hostField;
    @FXML
    protected TextField portField;
    @FXML
    protected TextField userNameField;
    @FXML
    protected TextField passwordField;
    @FXML
    protected TextField schemaField;
    @FXML
    protected ChoiceBox<String> encodingChoice;
    @FXML
    protected ChoiceBox<String> dbTypeChoice;
    protected MainUIController mainUIController;
    protected TabPaneController tabPaneController;
    protected boolean isUpdate = false;
    protected Integer primayKey;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
    }

    final void saveConnection() {
        DatabaseConfig config = extractConfigForUI();
        if (config == null) {
            return;
        }
        try {
            ConfigHelper.saveDatabaseConfig(this.isUpdate, primayKey, config);
            this.tabPaneController.getDialogStage().close();
            mainUIController.loadLeftDBTree();
        } catch (Exception e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }

    void setMainUIController(MainUIController controller) {
        this.mainUIController = controller;
        super.setDialogStage(mainUIController.getDialogStage());
    }

    public void setTabPaneController(TabPaneController tabPaneController) {
        this.tabPaneController = tabPaneController;
    }

    public DatabaseConfig extractConfigForUI() {
        String name = nameField.getText();
        String host = hostField.getText();
        String port = portField.getText();
        String userName = userNameField.getText();
        String password = passwordField.getText();
        String encoding = encodingChoice.getValue();
        String dbType = dbTypeChoice.getValue();
        String schema = schemaField.getText();
        DatabaseConfig config = new DatabaseConfig();
        config.setName(name);
        config.setDbType(dbType);
        config.setHost(host);
        config.setPort(port);
        config.setUsername(userName);
        config.setPassword(password);
        config.setSchema(schema);
        config.setEncoding(encoding);
        if (StringUtils.isAnyEmpty(name, host, port, userName, encoding, dbType, schema)) {
            AlertUtil.showWarnAlert("密码以外其他字段必填");
            return null;
        }
        return config;
    }

    public void setConfig(DatabaseConfig config) {
        isUpdate = true;
        primayKey = config.getId(); // save id for update config
        nameField.setText(config.getName());
        hostField.setText(config.getHost());
        portField.setText(config.getPort());
        userNameField.setText(config.getUsername());
        passwordField.setText(config.getPassword());
        encodingChoice.setValue(config.getEncoding());
        dbTypeChoice.setValue(config.getDbType());
        schemaField.setText(config.getSchema());
    }

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/FXMLPage.java
================================================
package com.zzg.mybatis.generator.controller;

/**
 * FXML User Interface enum
 * <p>
 * Created by Owen on 6/20/16.
 */
public enum FXMLPage {

    NEW_CONNECTION("fxml/newConnection.fxml"),
    SELECT_TABLE_COLUMN("fxml/selectTableColumn.fxml"),
    TABLE_COLUMN_CONFIG("fxml/tableColumnConfigs.fxml"),
    GENERATOR_CONFIG("fxml/generatorConfigs.fxml"),
    ;

    private String fxml;

    FXMLPage(String fxml) {
        this.fxml = fxml;
    }

    public String getFxml() {
        return this.fxml;
    }


}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/GeneratorConfigController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.zzg.mybatis.generator.model.GeneratorConfig;
import com.zzg.mybatis.generator.util.ConfigHelper;
import com.zzg.mybatis.generator.view.AlertUtil;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;

/**
 * 管理GeneratorConfig的Controller
 *
 * Created by Owen on 8/21/16.
 */
public class GeneratorConfigController extends BaseFXController {

    private static final Logger _LOG = LoggerFactory.getLogger(GeneratorConfigController.class);

    @FXML
    private TableView<GeneratorConfig> configTable;
    @FXML
    private TableColumn nameColumn;
    @FXML
    private TableColumn opsColumn;

    private MainUIController mainUIController;

    private GeneratorConfigController controller;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        controller = this;
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        // 自定义操作列
        opsColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        opsColumn.setCellFactory(cell -> {
            return new TableCell() {
                @Override
                protected void updateItem(Object item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || empty) {
                        setText(null);
                        setGraphic(null);
                    } else {
                        Button btn1 = new Button("应用");
                        Button btn2 = new Button("删除");
                        HBox hBox = new HBox();
                        hBox.setSpacing(10);
                        hBox.getChildren().add(btn1);
                        hBox.getChildren().add(btn2);
                        btn1.setOnAction(event -> {
                            try {
                                // 应用配置
                                GeneratorConfig generatorConfig = ConfigHelper.loadGeneratorConfig(item.toString());
                                mainUIController.setGeneratorConfigIntoUI(generatorConfig);
                                controller.closeDialogStage();
                            } catch (Exception e) {
                                AlertUtil.showErrorAlert(e.getMessage());
                            }
                        });
                        btn2.setOnAction(event -> {
                            try {
                                // 删除配置
                                _LOG.debug("item: {}", item);
                                ConfigHelper.deleteGeneratorConfig(item.toString());
                                refreshTableView();
                            } catch (Exception e) {
                                AlertUtil.showErrorAlert(e.getMessage());
                            }
                        });
                        setGraphic(hBox);
                    }
                }
            };
        });
        refreshTableView();
    }

    public void refreshTableView() {
        try {
            List<GeneratorConfig> configs = ConfigHelper.loadGeneratorConfigs();
            configTable.setItems(FXCollections.observableList(configs));
        } catch (Exception e) {
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }

    void setMainUIController(MainUIController mainUIController) {
        this.mainUIController = mainUIController;
    }

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/MainUIController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.jcraft.jsch.Session;
import com.zzg.mybatis.generator.bridge.MybatisGeneratorBridge;
import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.model.GeneratorConfig;
import com.zzg.mybatis.generator.model.UITableColumnVO;
import com.zzg.mybatis.generator.util.ConfigHelper;
import com.zzg.mybatis.generator.util.DbUtil;
import com.zzg.mybatis.generator.util.MyStringUtils;
import com.zzg.mybatis.generator.view.AlertUtil;
import com.zzg.mybatis.generator.view.UIProgressCallback;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.KeyEvent;
import javafx.stage.DirectoryChooser;
import javafx.util.Callback;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.mybatis.generator.config.ColumnOverride;
import org.mybatis.generator.config.IgnoredColumn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.io.File;
import java.net.URL;
import java.sql.SQLRecoverableException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;

public class MainUIController extends BaseFXController {

    private static final Logger _LOG = LoggerFactory.getLogger(MainUIController.class);
    private static final String FOLDER_NO_EXIST = "部分目录不存在,是否创建";
    // tool bar buttons
    @FXML
    private Label connectionLabel;
    @FXML
    private Label configsLabel;
    @FXML
    private TextField modelTargetPackage;
    @FXML
    private TextField mapperTargetPackage;
    @FXML
    private TextField daoTargetPackage;
    @FXML
    private TextField tableNameField;
    @FXML
    private TextField domainObjectNameField;
    @FXML
    private TextField generateKeysField;	//主键ID
    @FXML
    private TextField modelTargetProject;
    @FXML
    private TextField mappingTargetProject;
    @FXML
    private TextField daoTargetProject;
    @FXML
    private TextField mapperName;
    @FXML
    private TextField projectFolderField;
    @FXML
    private CheckBox offsetLimitCheckBox;
    @FXML
    private CheckBox commentCheckBox;
    @FXML
	private CheckBox overrideXML;
    @FXML
    private CheckBox needToStringHashcodeEquals;
    @FXML
    private CheckBox useLombokPlugin;
    @FXML
    private CheckBox forUpdateCheckBox;
    @FXML
    private CheckBox annotationDAOCheckBox;
    @FXML
    private CheckBox useTableNameAliasCheckbox;
    @FXML
    private CheckBox annotationCheckBox;
    @FXML
    private CheckBox useActualColumnNamesCheckbox;
    @FXML
    private CheckBox useExample;
    @FXML
    private CheckBox useDAOExtendStyle;
    @FXML
    private CheckBox useSchemaPrefix;
    @FXML
    private CheckBox jsr310Support;
    @FXML
    private TreeView<String> leftDBTree;
    @FXML
    public TextField filterTreeBox;
    // Current selected databaseConfig
    private DatabaseConfig selectedDatabaseConfig;
    // Current selected tableName
    private String tableName;

    private List<IgnoredColumn> ignoredColumns;

    private List<ColumnOverride> columnOverrides;

    @FXML
    private ChoiceBox<String> encodingChoice;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        ImageView dbImage = new ImageView("icons/computer.png");
        dbImage.setFitHeight(40);
        dbImage.setFitWidth(40);
        connectionLabel.setGraphic(dbImage);
        connectionLabel.setOnMouseClicked(event -> {
            TabPaneController controller = (TabPaneController) loadFXMLPage("新建数据库连接", FXMLPage.NEW_CONNECTION, false);
            controller.setMainUIController(this);
            controller.showDialogStage();
        });
        ImageView configImage = new ImageView("icons/config-list.png");
        configImage.setFitHeight(40);
        configImage.setFitWidth(40);
        configsLabel.setGraphic(configImage);
        configsLabel.setOnMouseClicked(event -> {
            GeneratorConfigController controller = (GeneratorConfigController) loadFXMLPage("配置", FXMLPage.GENERATOR_CONFIG, false);
            controller.setMainUIController(this);
            controller.showDialogStage();
        });
		useExample.setOnMouseClicked(event -> {
			if (useExample.isSelected()) {
				offsetLimitCheckBox.setDisable(false);
			} else {
				offsetLimitCheckBox.setDisable(true);
			}
		});
		// selectedProperty().addListener 解决应用配置的时候未触发Clicked事件
        useLombokPlugin.selectedProperty().addListener((observable, oldValue, newValue) -> {
            needToStringHashcodeEquals.setDisable(newValue);
        });

        leftDBTree.setShowRoot(false);
        leftDBTree.setRoot(new TreeItem<>());
        Callback<TreeView<String>, TreeCell<String>> defaultCellFactory = TextFieldTreeCell.forTreeView();
        filterTreeBox.addEventHandler(KeyEvent.KEY_PRESSED, ev -> {
            if (ev.getCode() == KeyCode.ENTER) {
                ObservableList<TreeItem<String>> schemas = leftDBTree.getRoot().getChildren();
                schemas.filtered(TreeItem::isExpanded).forEach(this::displayTables);
                ev.consume();
            }
        });
        leftDBTree.setCellFactory((TreeView<String> tv) -> {
            TreeCell<String> cell = defaultCellFactory.call(tv);

            cell.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
                int level = leftDBTree.getTreeItemLevel(cell.getTreeItem());
                TreeCell<String> treeCell = (TreeCell<String>) event.getSource();
                TreeItem<String> treeItem = treeCell.getTreeItem();
                if (level == 1) {
                    final ContextMenu contextMenu = new ContextMenu();
                    MenuItem item1 = new MenuItem("关闭连接");
                    item1.setOnAction(event1 -> treeItem.getChildren().clear());
	                MenuItem item2 = new MenuItem("编辑连接");
	                item2.setOnAction(event1 -> {
		                DatabaseConfig selectedConfig = (DatabaseConfig) treeItem.getGraphic().getUserData();
                        TabPaneController controller = (TabPaneController) loadFXMLPage("编辑数据库连接", FXMLPage.NEW_CONNECTION, false);
		                controller.setMainUIController(this);
		                controller.setConfig(selectedConfig);
		                controller.showDialogStage();
	                });
                    MenuItem item3 = new MenuItem("删除连接");
                    item3.setOnAction(event1 -> {
                        DatabaseConfig selectedConfig = (DatabaseConfig) treeItem.getGraphic().getUserData();
                        try {
                            ConfigHelper.deleteDatabaseConfig(selectedConfig);
                            this.loadLeftDBTree();
                        } catch (Exception e) {
                            AlertUtil.showErrorAlert("Delete connection failed! Reason: " + e.getMessage());
                        }
                    });
                    contextMenu.getItems().addAll(item1, item2, item3);
                    cell.setContextMenu(contextMenu);
                }
                if (event.getClickCount() == 2) {
                    if(treeItem == null) {
                        return ;
                    }
                    treeItem.setExpanded(true);
                    if (level == 1) {
                        displayTables(treeItem);
                    } else if (level == 2) { // left DB tree level3
                        String tableName = treeCell.getTreeItem().getValue();
                        selectedDatabaseConfig = (DatabaseConfig) treeItem.getParent().getGraphic().getUserData();
                        this.tableName = tableName;
                        tableNameField.setText(tableName);
                        domainObjectNameField.setText(MyStringUtils.dbStringToCamelStyle(tableName));
                        mapperName.setText(domainObjectNameField.getText().concat("DAO"));
                    }
                }
            });
            return cell;
        });
        loadLeftDBTree();
		setTooltip();
		//默认选中第一个,否则如果忘记选择,没有对应错误提示
        encodingChoice.getSelectionModel().selectFirst();
	}

	private void displayTables(TreeItem<String> treeItem) {
        if(treeItem == null) {
            return ;
        }
        if (!treeItem.isExpanded()) {
            return;
        }
        DatabaseConfig selectedConfig = (DatabaseConfig) treeItem.getGraphic().getUserData();
        try {
            String filter = filterTreeBox.getText();
            List<String> tables = DbUtil.getTableNames(selectedConfig, filter);
            if (tables.size() > 0) {
                ObservableList<TreeItem<String>> children = treeItem.getChildren();
                children.clear();
                for (String tableName : tables) {
                    TreeItem<String> newTreeItem = new TreeItem<>();
                    ImageView imageView = new ImageView("icons/table.png");
                    imageView.setFitHeight(16);
                    imageView.setFitWidth(16);
                    newTreeItem.setGraphic(imageView);
                    newTreeItem.setValue(tableName);
                    children.add(newTreeItem);
                }
            }else if (StringUtils.isNotBlank(filter)){
                treeItem.getChildren().clear();
            }
            if (StringUtils.isNotBlank(filter)) {
                ImageView imageView = new ImageView("icons/filter.png");
                imageView.setFitHeight(16);
                imageView.setFitWidth(16);
                imageView.setUserData(treeItem.getGraphic().getUserData());
                treeItem.setGraphic(imageView);
            }else {
                ImageView dbImage = new ImageView("icons/computer.png");
                dbImage.setFitHeight(16);
                dbImage.setFitWidth(16);
                dbImage.setUserData(treeItem.getGraphic().getUserData());
                treeItem.setGraphic(dbImage);
            }
        } catch (SQLRecoverableException e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert("连接超时");
        } catch (Exception e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }

	private void setTooltip() {
		encodingChoice.setTooltip(new Tooltip("生成文件的编码,必选"));
		generateKeysField.setTooltip(new Tooltip("insert时可以返回主键ID"));
		offsetLimitCheckBox.setTooltip(new Tooltip("是否要生成分页查询代码"));
		commentCheckBox.setTooltip(new Tooltip("使用数据库的列注释作为实体类字段名的Java注释 "));
		useActualColumnNamesCheckbox.setTooltip(new Tooltip("是否使用数据库实际的列名作为实体类域的名称"));
		useTableNameAliasCheckbox.setTooltip(new Tooltip("在Mapper XML文件中表名使用别名,并且列全部使用as查询"));
		overrideXML.setTooltip(new Tooltip("重新生成时把原XML文件覆盖,否则是追加"));
        useDAOExtendStyle.setTooltip(new Tooltip("将通用接口方法放在公共接口中,DAO接口留空"));
        forUpdateCheckBox.setTooltip(new Tooltip("在Select语句中增加for update后缀"));
        useLombokPlugin.setTooltip(new Tooltip("实体类使用Lombok @Data简化代码"));
	}

    void loadLeftDBTree() {
        TreeItem rootTreeItem = leftDBTree.getRoot();
        rootTreeItem.getChildren().clear();
        try {
            List<DatabaseConfig> dbConfigs = ConfigHelper.loadDatabaseConfig();
            for (DatabaseConfig dbConfig : dbConfigs) {
                TreeItem<String> treeItem = new TreeItem<>();
                treeItem.setValue(dbConfig.getName());
                ImageView dbImage = new ImageView("icons/computer.png");
                dbImage.setFitHeight(16);
                dbImage.setFitWidth(16);
                dbImage.setUserData(dbConfig);
                treeItem.setGraphic(dbImage);
                rootTreeItem.getChildren().add(treeItem);
            }
        } catch (Exception e) {
            _LOG.error("connect db failed, reason", e);
            AlertUtil.showErrorAlert(e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e));
        }
    }

    @FXML
    public void chooseProjectFolder() {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        File selectedFolder = directoryChooser.showDialog(getPrimaryStage());
        if (selectedFolder != null) {
            projectFolderField.setText(selectedFolder.getAbsolutePath());
        }
    }

    @FXML
    public void generateCode() {
        if (tableName == null) {
            AlertUtil.showWarnAlert("请先在左侧选择数据库表");
            return;
        }
        String result = validateConfig();
		if (result != null) {
			AlertUtil.showErrorAlert(result);
			return;
		}
        GeneratorConfig generatorConfig = getGeneratorConfigFromUI();
        if (!checkDirs(generatorConfig)) {
            return;
        }

        MybatisGeneratorBridge bridge = new MybatisGeneratorBridge();
        bridge.setGeneratorConfig(generatorConfig);
        bridge.setDatabaseConfig(selectedDatabaseConfig);
        bridge.setIgnoredColumns(ignoredColumns);
        bridge.setColumnOverrides(columnOverrides);
        UIProgressCallback alert = new UIProgressCallback(Alert.AlertType.INFORMATION);
        bridge.setProgressCallback(alert);
        alert.show();
        PictureProcessStateController pictureProcessStateController = null;
        try {
            //Engage PortForwarding
            Session sshSession = DbUtil.getSSHSession(selectedDatabaseConfig);
            DbUtil.engagePortForwarding(sshSession, selectedDatabaseConfig);

            if (sshSession != null) {
                pictureProcessStateController = new PictureProcessStateController();
                pictureProcessStateController.setDialogStage(getDialogStage());
                pictureProcessStateController.startPlay();
            }

            bridge.generate();

            if (pictureProcessStateController != null) {
                Task task = new Task<Void>() {
                    @Override
                    protected Void call() throws Exception {
                        Thread.sleep(3000);
                        return null;
                    }
                };
                PictureProcessStateController finalPictureProcessStateController = pictureProcessStateController;
                task.setOnSucceeded(event -> {
                    finalPictureProcessStateController.close();
                });
                task.setOnFailed(event -> {
                    finalPictureProcessStateController.close();
                });
                new Thread(task).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            AlertUtil.showErrorAlert(e.getMessage());
            if (pictureProcessStateController != null) {
                pictureProcessStateController.close();
                pictureProcessStateController.playFailState(e.getMessage(), true);
            }
        }
    }

	private String validateConfig() {
		String projectFolder = projectFolderField.getText();
		if (StringUtils.isEmpty(projectFolder))  {
			return "项目目录不能为空";
		}
		if (StringUtils.isEmpty(domainObjectNameField.getText()))  {
			return "类名不能为空";
		}
		if (StringUtils.isAnyEmpty(modelTargetPackage.getText(), mapperTargetPackage.getText(), daoTargetPackage.getText())) {
			return "包名不能为空";
		}

		return null;
	}

	@FXML
    public void saveGeneratorConfig() {
        TextInputDialog dialog = new TextInputDialog("");
        dialog.setTitle("保存当前配置");
        dialog.setContentText("请输入配置名称");
        Optional<String> result = dialog.showAndWait();
        if (result.isPresent()) {
            String name = result.get();
            if (StringUtils.isEmpty(name)) {
                AlertUtil.showErrorAlert("名称不能为空");
                return;
            }
            _LOG.info("user choose name: {}", name);
            try {
                GeneratorConfig generatorConfig = getGeneratorConfigFromUI();
                generatorConfig.setName(name);
                ConfigHelper.deleteGeneratorConfig(name);
                ConfigHelper.saveGeneratorConfig(generatorConfig);
            } catch (Exception e) {
                _LOG.error("保存配置失败", e);
                AlertUtil.showErrorAlert("保存配置失败");
            }
        }
    }

    public GeneratorConfig getGeneratorConfigFromUI() {
        GeneratorConfig generatorConfig = new GeneratorConfig();
        generatorConfig.setProjectFolder(projectFolderField.getText());
        generatorConfig.setModelPackage(modelTargetPackage.getText());
        generatorConfig.setGenerateKeys(generateKeysField.getText());
        generatorConfig.setModelPackageTargetFolder(modelTargetProject.getText());
        generatorConfig.setDaoPackage(daoTargetPackage.getText());
        generatorConfig.setDaoTargetFolder(daoTargetProject.getText());
        generatorConfig.setMapperName(mapperName.getText());
        generatorConfig.setMappingXMLPackage(mapperTargetPackage.getText());
        generatorConfig.setMappingXMLTargetFolder(mappingTargetProject.getText());
        generatorConfig.setTableName(tableNameField.getText());
        generatorConfig.setDomainObjectName(domainObjectNameField.getText());
        generatorConfig.setOffsetLimit(offsetLimitCheckBox.isSelected());
        generatorConfig.setComment(commentCheckBox.isSelected());
        generatorConfig.setOverrideXML(overrideXML.isSelected());
        generatorConfig.setNeedToStringHashcodeEquals(needToStringHashcodeEquals.isSelected());
        generatorConfig.setUseLombokPlugin(useLombokPlugin.isSelected());
        generatorConfig.setUseTableNameAlias(useTableNameAliasCheckbox.isSelected());
        generatorConfig.setNeedForUpdate(forUpdateCheckBox.isSelected());
        generatorConfig.setAnnotationDAO(annotationDAOCheckBox.isSelected());
        generatorConfig.setAnnotation(annotationCheckBox.isSelected());
        generatorConfig.setUseActualColumnNames(useActualColumnNamesCheckbox.isSelected());
        generatorConfig.setEncoding(encodingChoice.getValue());
        generatorConfig.setUseExample(useExample.isSelected());
        generatorConfig.setUseDAOExtendStyle(useDAOExtendStyle.isSelected());
        generatorConfig.setUseSchemaPrefix(useSchemaPrefix.isSelected());
        generatorConfig.setJsr310Support(jsr310Support.isSelected());
        return generatorConfig;
    }

    public void setGeneratorConfigIntoUI(GeneratorConfig generatorConfig) {
        projectFolderField.setText(generatorConfig.getProjectFolder());
        modelTargetPackage.setText(generatorConfig.getModelPackage());
        generateKeysField.setText(generatorConfig.getGenerateKeys());
        modelTargetProject.setText(generatorConfig.getModelPackageTargetFolder());
        daoTargetPackage.setText(generatorConfig.getDaoPackage());
		daoTargetProject.setText(generatorConfig.getDaoTargetFolder());
		mapperTargetPackage.setText(generatorConfig.getMappingXMLPackage());
        mappingTargetProject.setText(generatorConfig.getMappingXMLTargetFolder());
        if (StringUtils.isBlank(tableNameField.getText())) {
            tableNameField.setText(generatorConfig.getTableName());
            mapperName.setText(generatorConfig.getMapperName());
            domainObjectNameField.setText(generatorConfig.getDomainObjectName());
        }
        offsetLimitCheckBox.setSelected(generatorConfig.isOffsetLimit());
        commentCheckBox.setSelected(generatorConfig.isComment());
        overrideXML.setSelected(generatorConfig.isOverrideXML());
        needToStringHashcodeEquals.setSelected(generatorConfig.isNeedToStringHashcodeEquals());
        useLombokPlugin.setSelected(generatorConfig.isUseLombokPlugin());
        useTableNameAliasCheckbox.setSelected(generatorConfig.getUseTableNameAlias());
        forUpdateCheckBox.setSelected(generatorConfig.isNeedForUpdate());
        annotationDAOCheckBox.setSelected(generatorConfig.isAnnotationDAO());
        annotationCheckBox.setSelected(generatorConfig.isAnnotation());
        useActualColumnNamesCheckbox.setSelected(generatorConfig.isUseActualColumnNames());
        encodingChoice.setValue(generatorConfig.getEncoding());
        useExample.setSelected(generatorConfig.isUseExample());
        useDAOExtendStyle.setSelected(generatorConfig.isUseDAOExtendStyle());
        useSchemaPrefix.setSelected(generatorConfig.isUseSchemaPrefix());
        jsr310Support.setSelected(generatorConfig.isJsr310Support());
    }

    @FXML
    public void openTableColumnCustomizationPage() {
        if (tableName == null) {
            AlertUtil.showWarnAlert("请先在左侧选择数据库表");
            return;
        }
        SelectTableColumnController controller = (SelectTableColumnController) loadFXMLPage("定制列", FXMLPage.SELECT_TABLE_COLUMN, true);
        controller.setMainUIController(this);
        try {
            // If select same schema and another table, update table data
            if (!tableName.equals(controller.getTableName())) {
                List<UITableColumnVO> tableColumns = DbUtil.getTableColumns(selectedDatabaseConfig, tableName);
                controller.setColumnList(FXCollections.observableList(tableColumns));
                controller.setTableName(tableName);
            }
            controller.showDialogStage();
        } catch (Exception e) {
            _LOG.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }

    public void setIgnoredColumns(List<IgnoredColumn> ignoredColumns) {
        this.ignoredColumns = ignoredColumns;
    }

    public void setColumnOverrides(List<ColumnOverride> columnOverrides) {
        this.columnOverrides = columnOverrides;
    }

    /**
     * 检查并创建不存在的文件夹
     *
     * @return
     */
    private boolean checkDirs(GeneratorConfig config) {
		List<String> dirs = new ArrayList<>();
		dirs.add(config.getProjectFolder());
		dirs.add(config.getProjectFolder().concat("/").concat(config.getModelPackageTargetFolder()));
		dirs.add(config.getProjectFolder().concat("/").concat(config.getDaoTargetFolder()));
		dirs.add(config.getProjectFolder().concat("/").concat(config.getMappingXMLTargetFolder()));
		boolean haveNotExistFolder = false;
		for (String dir : dirs) {
			File file = new File(dir);
			if (!file.exists()) {
				haveNotExistFolder = true;
			}
		}
		if (haveNotExistFolder) {
			Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
			alert.setContentText(FOLDER_NO_EXIST);
			Optional<ButtonType> optional = alert.showAndWait();
			if (optional.isPresent()) {
				if (ButtonType.OK == optional.get()) {
					try {
						for (String dir : dirs) {
							FileUtils.forceMkdir(new File(dir));
						}
						return true;
					} catch (Exception e) {
						AlertUtil.showErrorAlert("创建目录失败,请检查目录是否是文件而非目录");
					}
				} else {
					return false;
				}
			}
		}
        return true;
    }

    @FXML
    public void openTargetFolder() {
        GeneratorConfig generatorConfig = getGeneratorConfigFromUI();
        String projectFolder = generatorConfig.getProjectFolder();
        try {
            Desktop.getDesktop().browse(new File(projectFolder).toURI());
        }catch (Exception e) {
            AlertUtil.showErrorAlert("打开目录失败,请检查目录是否填写正确" + e.getMessage());
        }

    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/OverSshController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.util.ConfigHelper;
import com.zzg.mybatis.generator.util.DbUtil;
import com.zzg.mybatis.generator.view.AlertUtil;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Paint;
import javafx.stage.FileChooser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.*;

/**
 * Project: mybatis-generator-gui
 *
 * @author slankka on 2018/12/30.
 */
public class OverSshController extends DbConnectionController {

    private Logger logger = LoggerFactory.getLogger(OverSshController.class);

    @FXML
    public HBox pubkeyBox;
    @FXML
    public Label lPortLabel;
    @FXML
    public TextField sshUserField;
    @FXML
    public ChoiceBox<String> authTypeChoice;
    @FXML
    public Label sshPasswordLabel;
    @FXML
    public PasswordField sshPasswordField;
    @FXML
    private TextField sshHostField;
    @FXML
    private TextField sshdPortField;
    @FXML
    private TextField lportField;
    @FXML
    private TextField rportField;
    @FXML
    private Label note;
    @FXML
    private Label pubkeyBoxLabel;
    @FXML
    private TextField sshPubKeyField;
    @FXML
    public PasswordField sshPubkeyPasswordField;
    @FXML
    public Label sshPubkeyPasswordLabel;
    @FXML
    public Label sshPubkeyPasswordNote;

    private FileChooser fileChooser = new FileChooser();

    private File privateKey;
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        fileChooser.setTitle("选择SSH秘钥文件");
        fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));
        authTypeChoice.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if ("PubKey".equals(newValue)) {
                //公钥认证
                sshPasswordField.setVisible(false);
                sshPasswordLabel.setVisible(false);
                pubkeyBox.setVisible(true);
                pubkeyBoxLabel.setVisible(true);
                sshPubkeyPasswordField.setVisible(true);
                sshPubkeyPasswordLabel.setVisible(true);
                sshPubkeyPasswordNote.setVisible(true);
            }else {
                //密码认证
                pubkeyBox.setVisible(false);
                pubkeyBoxLabel.setVisible(false);
                sshPubkeyPasswordField.setVisible(false);
                sshPubkeyPasswordLabel.setVisible(false);
                sshPubkeyPasswordNote.setVisible(false);
                sshPasswordLabel.setVisible(true);
                sshPasswordField.setVisible(true);
            }
        });
    }

    public void setDbConnectionConfig(DatabaseConfig databaseConfig) {
        if (databaseConfig == null) {
            return;
        }
        isUpdate = true;
        super.setConfig(databaseConfig);
        this.sshdPortField.setText(databaseConfig.getSshPort());
        this.sshHostField.setText(databaseConfig.getSshHost());
        this.lportField.setText(databaseConfig.getLport());
        this.rportField.setText(databaseConfig.getRport());
        this.sshUserField.setText(databaseConfig.getSshUser());
        this.sshPasswordField.setText(databaseConfig.getSshPassword());
        //例如:默认从本机的 3306 -> 转发到 3306
        if (StringUtils.isBlank(this.lportField.getText())) {
            this.lportField.setText(databaseConfig.getPort());
        }
        if (StringUtils.isBlank(this.rportField.getText())) {
            this.rportField.setText(databaseConfig.getPort());
        }
        if (StringUtils.isNotBlank(databaseConfig.getPrivateKey())) {
            this.sshPubKeyField.setText(databaseConfig.getPrivateKey());
            this.sshPubkeyPasswordField.setText(databaseConfig.getPrivateKeyPassword());
            authTypeChoice.getSelectionModel().select("PubKey");
        }
        checkInput();
    }

    @FXML
    public void checkInput() {
        DatabaseConfig databaseConfig = extractConfigFromUi();
        if (authTypeChoice.getValue().equals("Password") && (
            StringUtils.isBlank(databaseConfig.getSshHost())
                || StringUtils.isBlank(databaseConfig.getSshPort())
                || StringUtils.isBlank(databaseConfig.getSshUser())
                || StringUtils.isBlank(databaseConfig.getSshPassword())
        )
            || authTypeChoice.getValue().equals("PubKey") && (
            StringUtils.isBlank(databaseConfig.getSshHost())
                || StringUtils.isBlank(databaseConfig.getSshPort())
                || StringUtils.isBlank(databaseConfig.getSshUser())
                || StringUtils.isBlank(databaseConfig.getPrivateKey())
        )
        ) {
            note.setText("当前SSH配置输入不完整,OVER SSH不生效");
            note.setTextFill(Paint.valueOf("#ff666f"));
        } else {
            note.setText("当前SSH配置生效");
            note.setTextFill(Paint.valueOf("#5da355"));
        }
    }

    public void setLPortLabelText(String text) {
        lPortLabel.setText(text);
    }

    public void recoverNotice() {
        this.lPortLabel.setText("注意不要填写被其他程序占用的端口");
    }

    public DatabaseConfig extractConfigFromUi() {
        String name = nameField.getText();
        String host = hostField.getText();
        String port = portField.getText();
        String userName = userNameField.getText();
        String password = passwordField.getText();
        String encoding = encodingChoice.getValue();
        String dbType = dbTypeChoice.getValue();
        String schema = schemaField.getText();
        String authType = authTypeChoice.getValue();
        DatabaseConfig config = new DatabaseConfig();
        config.setName(name);
        config.setDbType(dbType);
        config.setHost(host);
        config.setPort(port);
        config.setUsername(userName);
        config.setPassword(password);
        config.setSchema(schema);
        config.setEncoding(encoding);
        config.setSshHost(this.sshHostField.getText());
        config.setSshPort(this.sshdPortField.getText());
        config.setLport(this.lportField.getText());
        config.setRport(this.rportField.getText());
        config.setSshUser(this.sshUserField.getText());
        config.setSshPassword(this.sshPasswordField.getText());
        if ("PubKey".equals(authType)) {
            config.setPrivateKey(this.privateKey.getAbsolutePath());
            config.setPrivateKeyPassword(this.sshPubkeyPasswordField.getText());
        }
        return config;
    }

    public void saveConfig() {
        DatabaseConfig databaseConfig = extractConfigFromUi();
        if (StringUtils.isAnyEmpty(
                databaseConfig.getName(),
                databaseConfig.getHost(),
                databaseConfig.getPort(),
                databaseConfig.getUsername(),
                databaseConfig.getEncoding(),
                databaseConfig.getDbType(),
                databaseConfig.getSchema())) {
            AlertUtil.showWarnAlert("密码以外其他字段必填");
            return;
        }
        try {
            ConfigHelper.saveDatabaseConfig(this.isUpdate, primayKey, databaseConfig);
            this.tabPaneController.getDialogStage().close();
            mainUIController.loadLeftDBTree();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            AlertUtil.showErrorAlert(e.getMessage());
        }
    }

    @FXML
    public void testSSH() {
        Session session = DbUtil.getSSHSession(extractConfigFromUi());
        if (session == null) {
            AlertUtil.showErrorAlert("请检查主机,端口,用户名,以及密码/秘钥是否填写正确");
            return;
        }
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<?> result = executorService.submit(() -> {
            try {
                session.connect();
            } catch (JSchException e) {
                logger.error("Connect Over SSH failed", e);
                throw new RuntimeException(e.getMessage());
            }
        });
        executorService.shutdown();
        try {
            boolean b = executorService.awaitTermination(5, TimeUnit.SECONDS);
            if (!b) {
                throw new TimeoutException("连接超时");
            }
            result.get();
            AlertUtil.showInfoAlert("连接SSH服务器成功,恭喜你可以使用OverSSH功能");
            recoverNotice();
        } catch (Exception e) {
            AlertUtil.showErrorAlert("请检查主机,端口,用户名,以及密码/秘钥是否填写正确: " + e.getMessage());
        } finally {
            DbUtil.shutdownPortForwarding(session);
        }
    }

    @FXML
    public void reset(ActionEvent actionEvent) {
        this.sshUserField.clear();
        this.sshPasswordField.clear();
        this.sshdPortField.clear();
        this.sshHostField.clear();
        this.lportField.clear();
        this.rportField.clear();
        this.sshPubKeyField.clear();
        recoverNotice();
    }

    public void choosePubKey(ActionEvent actionEvent) {
        this.privateKey = fileChooser.showOpenDialog(getDialogStage());
        sshPubKeyField.setText(this.privateKey.getAbsolutePath());
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/PictureProcessStateController.java
================================================
package com.zzg.mybatis.generator.controller;

import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;


import static javafx.scene.paint.Color.DARKSEAGREEN;

public class PictureProcessStateController {
    private ImageView dbImage = new ImageView("icons/SSH_tunnel.png");
    private final Rectangle rect = new Rectangle(20, 20, 30, 30);
    private final RotateTransition rotateTransition = new RotateTransition();
    private final Text text = new Text("");
    private final Stage dialogStage = new Stage(StageStyle.TRANSPARENT);
    private double initX;
    private double initY;
    private Stage parentStage;
    private final Button button = new Button("");
    public void setDialogStage(Stage stage) {
        this.parentStage = stage;
    }

    public void startPlay() {
        dbImage.setFitHeight(192);
        dbImage.setFitWidth(798);
        Group rootGroup = new Group();
        Scene scene = new Scene(rootGroup, 800, 212, Color.TRANSPARENT);
        dialogStage.initModality(Modality.APPLICATION_MODAL);
        dialogStage.setScene(scene);
        dialogStage.initOwner(parentStage);
        dialogStage.centerOnScreen();
        dialogStage.setTitle("OverSSH");

        rect.setArcHeight(10);
        rect.setArcWidth(10);
        rect.setFill(DARKSEAGREEN);

        rotateTransition.setNode(rect);
        rotateTransition.setDuration(Duration.seconds(0.8d));
        rotateTransition.setFromAngle(0);
        rotateTransition.setToAngle(720);
        rotateTransition.setCycleCount(Timeline.INDEFINITE);
        rotateTransition.setAutoReverse(true);
        VBox vBoxRect = new VBox();
        vBoxRect.setAlignment(Pos.TOP_CENTER);
        vBoxRect.getChildren().add(rect);
        VBox.setMargin(rect, new Insets(125, 0, 0, 350));
        rotateTransition.play();


        text.setFont(Font.font(12));
        VBox vBoxLabel = new VBox();
        vBoxLabel.getChildren().add(text);
        VBox.setMargin(text, new Insets(175, 0, 15, 40));


        button.setPrefSize(90, 40);
        HBox hBoxButton = new HBox();
        hBoxButton.setPrefSize(505, 170);
        hBoxButton.getChildren().add(button);
        hBoxButton.setAlignment(Pos.BOTTOM_RIGHT);
        hBoxButton.getStylesheets().add(Thread.currentThread().getContextClassLoader().getResource("style.css").toExternalForm());
        HBox.setMargin(button, new Insets(0, 15, 5, 0));
        button.setStyle("-fx-border-width: 0px;");
        button.setStyle("-fx-border-color: transparent;");
        button.setStyle("-fx-background-color: transparent;");
        rootGroup.getChildren().addAll(dbImage, vBoxRect, vBoxLabel, hBoxButton);
        dialogStage.show();

        button.setOnMouseClicked((event) -> dialogStage.close());

        rootGroup.setOnMousePressed((me) -> {
                initX = me.getScreenX() - dialogStage.getX();
                initY = me.getScreenY() - dialogStage.getY();
        });
        rootGroup.setOnMouseDragged((me) -> {
            dialogStage.setX(me.getScreenX() - initX);
            dialogStage.setY(me.getScreenY() - initY);
        });
    }

    public void playFailState(String message, boolean showButton) {
        rect.setFill(Color.ORANGERED);
        rotateTransition.stop();
        dbImage.setImage(new Image("icons/SSH_tunnel_disconnected.png"));
        rotateTransition.setDuration(Duration.seconds(3));
        rotateTransition.play();
        text.setText(message);
        if (showButton) {
            showCloseButton();
        }
        if (!dialogStage.isShowing()) {
            dialogStage.show();
        }
    }

    private void showCloseButton() {
        button.getStyleClass().add("btn");
        button.getStyleClass().add("btn-default");
        button.setStyle("-fx-border-width: 1px;");
        button.setStyle("-fx-background-color: #fff;");
        button.setText("我知道了");
    }

    public void playSuccessState(String message, boolean showButton) {
        rect.setFill(DARKSEAGREEN);
        rotateTransition.stop();
        dbImage.setImage(new Image("icons/SSH_tunnel.png"));
        rotateTransition.setDuration(Duration.seconds(0.8));
        rotateTransition.play();
        text.setText(message);
        if (showButton) {
            showCloseButton();
        }
    }

    public void close() {
        dialogStage.close();
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/SelectTableColumnController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.zzg.mybatis.generator.model.UITableColumnVO;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import org.mybatis.generator.config.ColumnOverride;
import org.mybatis.generator.config.IgnoredColumn;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

/**
 * Created by Owen on 6/20/16.
 */
public class SelectTableColumnController extends BaseFXController {

    @FXML
    private TableView<UITableColumnVO> columnListView;
    @FXML
    private TableColumn<UITableColumnVO, Boolean> checkedColumn;
    @FXML
    private TableColumn<UITableColumnVO, String> columnNameColumn;
    @FXML
    private TableColumn<UITableColumnVO, String> jdbcTypeColumn;
    @FXML
    private TableColumn<UITableColumnVO, String> javaTypeColumn;
    @FXML
    private TableColumn<UITableColumnVO, String> propertyNameColumn;
    @FXML
    private TableColumn<UITableColumnVO, String> typeHandlerColumn;

    private MainUIController mainUIController;

    private String tableName;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // cellvaluefactory
        checkedColumn.setCellValueFactory(new PropertyValueFactory<>("checked"));
        columnNameColumn.setCellValueFactory(new PropertyValueFactory<>("columnName"));
        jdbcTypeColumn.setCellValueFactory(new PropertyValueFactory<>("jdbcType"));
        propertyNameColumn.setCellValueFactory(new PropertyValueFactory<>("propertyName"));
        typeHandlerColumn.setCellValueFactory(new PropertyValueFactory<>("typeHandler"));
        // Cell Factory that customize how the cell should render
        checkedColumn.setCellFactory(CheckBoxTableCell.forTableColumn(checkedColumn));
        jdbcTypeColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        // handle commit event to save the user input data
        jdbcTypeColumn.setOnEditCommit(event -> {
            event.getTableView().getItems().get(event.getTablePosition().getRow()).setJdbcType(event.getNewValue());
        });
        javaTypeColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        // handle commit event to save the user input data
        javaTypeColumn.setOnEditCommit(event -> {
            event.getTableView().getItems().get(event.getTablePosition().getRow()).setJavaType(event.getNewValue());
        });
        propertyNameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        propertyNameColumn.setOnEditCommit(event -> {
            event.getTableView().getItems().get(event.getTablePosition().getRow()).setPropertyName(event.getNewValue());
        });
        typeHandlerColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        typeHandlerColumn.setOnEditCommit(event -> {
            event.getTableView().getItems().get(event.getTablePosition().getRow()).setTypeHandle(event.getNewValue());
        });
    }

    @FXML
    public void ok() {
        ObservableList<UITableColumnVO> items = columnListView.getItems();
        if (items != null && items.size() > 0) {
            List<IgnoredColumn> ignoredColumns = new ArrayList<>();
            List<ColumnOverride> columnOverrides = new ArrayList<>();
            items.stream().forEach(item -> {
                if (!item.getChecked()) {
                    IgnoredColumn ignoredColumn = new IgnoredColumn(item.getColumnName());
                    ignoredColumns.add(ignoredColumn);
                } else if (item.getTypeHandle() != null || item.getJavaType() != null || item.getPropertyName() != null) { // unchecked and have typeHandler value
                    ColumnOverride columnOverride = new ColumnOverride(item.getColumnName());
                    columnOverride.setTypeHandler(item.getTypeHandle());
                    columnOverride.setJdbcType(item.getJdbcType());
                    columnOverride.setJavaProperty(item.getPropertyName());
                    columnOverride.setJavaType(item.getJavaType());
                    columnOverrides.add(columnOverride);
                }
            });
            mainUIController.setIgnoredColumns(ignoredColumns);
            mainUIController.setColumnOverrides(columnOverrides);
        }
        getDialogStage().close();
    }

    @FXML
    public void cancel() {
        getDialogStage().close();
    }

    @FXML
    public void configAction() {
        TableColumnConfigsController controller = (TableColumnConfigsController) loadFXMLPage("定制列配置", FXMLPage.TABLE_COLUMN_CONFIG,true);
        controller.setColumnListView(this.columnListView);
        controller.setTableName(this.tableName);
        controller.showDialogStage();
    }

    public void setColumnList(ObservableList<UITableColumnVO> columns) {
        columnListView.setItems(columns);
    }

    public void setMainUIController(MainUIController mainUIController) {
        this.mainUIController = mainUIController;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }


}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/TabPaneController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.jcraft.jsch.Session;
import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.util.DbUtil;
import com.zzg.mybatis.generator.view.AlertUtil;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.EOFException;
import java.net.URL;
import java.util.ResourceBundle;

/**
 * Project: mybatis-generator-gui
 *
 * @author github.com/slankka on 2019/1/22.
 */
public class TabPaneController extends BaseFXController {
    private static Logger logger = LoggerFactory.getLogger(TabPaneController.class);

    @FXML
    private TabPane tabPane;

    @FXML
    private DbConnectionController tabControlAController;

    @FXML
    private OverSshController tabControlBController;

    private boolean isOverssh;

    private MainUIController mainUIController;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        tabPane.setPrefHeight(((AnchorPane) tabPane.getSelectionModel().getSelectedItem().getContent()).getPrefHeight());
        tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            isOverssh = observable.getValue().getText().equals("SSH");
            tabPane.prefHeightProperty().bind(((AnchorPane) tabPane.getSelectionModel().getSelectedItem().getContent()).prefHeightProperty());
            getDialogStage().close();
            getDialogStage().show();
        });
    }

    public void setMainUIController(MainUIController mainUIController) {
        this.mainUIController = mainUIController;
        this.tabControlAController.setMainUIController(mainUIController);
        this.tabControlAController.setTabPaneController(this);
        this.tabControlBController.setMainUIController(mainUIController);
        this.tabControlBController.setTabPaneController(this);
    }

    public void setConfig(DatabaseConfig selectedConfig) {
        tabControlAController.setConfig(selectedConfig);
        tabControlBController.setDbConnectionConfig(selectedConfig);
        if (StringUtils.isNoneBlank(
                selectedConfig.getSshHost(),
                selectedConfig.getSshPassword(),
                selectedConfig.getSshPort(),
                selectedConfig.getSshUser(),
                selectedConfig.getLport())) {
            logger.info("Found SSH based Config");
            tabPane.getSelectionModel().selectLast();
        }
    }

    private DatabaseConfig extractConfigForUI() {
        if (isOverssh) {
            return tabControlBController.extractConfigFromUi();
        } else {
            return tabControlAController.extractConfigForUI();
        }
    }

    @FXML
    void saveConnection() {
        if (isOverssh) {
            tabControlBController.saveConfig();
        } else {
            tabControlAController.saveConnection();
        }
    }


    @FXML
    void testConnection() {
        DatabaseConfig config = extractConfigForUI();
        if (config == null) {
            return;
        }
        if (StringUtils.isAnyEmpty(config.getName(),
                config.getHost(),
                config.getPort(),
                config.getUsername(),
                config.getEncoding(),
                config.getDbType(),
                config.getSchema())) {
            AlertUtil.showWarnAlert("密码以外其他字段必填");
            return;
        }
        Session sshSession = DbUtil.getSSHSession(config);
        if (isOverssh && sshSession != null) {
            PictureProcessStateController pictureProcessState = new PictureProcessStateController();
            pictureProcessState.setDialogStage(getDialogStage());
            pictureProcessState.startPlay();
            //如果不用异步,则视图会等方法返回才会显示
            Task task = new Task<Void>() {
                @Override
                protected Void call() throws Exception {
                    DbUtil.engagePortForwarding(sshSession, config);
                    DbUtil.getConnection(config);
                    return null;
                }
            };
            task.setOnFailed(event -> {
                Throwable e = task.getException();
                logger.error("task Failed", e);
                if (e instanceof RuntimeException) {
                    if (e.getMessage().equals("Address already in use: JVM_Bind")) {
                        tabControlBController.setLPortLabelText(config.getLport() + "已经被占用,请换其他端口");
                    }
                    //端口转发一定不成功,导致数据库连接不上
                    pictureProcessState.playFailState("连接失败:" + e.getMessage(), true);
                    return;
                }

                if (e.getCause() instanceof EOFException) {
                    pictureProcessState.playFailState("连接失败, 请检查数据库的主机名,并且检查端口和目标端口是否一致", true);
                    //端口转发已经成功,但是数据库连接不上,故需要释放连接
                    DbUtil.shutdownPortForwarding(sshSession);
                    return;
                }
                pictureProcessState.playFailState("连接失败:" + e.getMessage(), true);
                //可能是端口转发已经成功,但是数据库连接不上,故需要释放连接
                DbUtil.shutdownPortForwarding(sshSession);
            });
            task.setOnSucceeded(event -> {
                try {
                    pictureProcessState.playSuccessState("连接成功", true);
                    DbUtil.shutdownPortForwarding(sshSession);
                    tabControlBController.recoverNotice();
                } catch (Exception e) {
                    logger.error("", e);
                }
            });
            new Thread(task).start();
        } else {
            try {
                DbUtil.getConnection(config);
                AlertUtil.showInfoAlert("连接成功");
            } catch (RuntimeException e) {
                logger.error("", e);
                AlertUtil.showWarnAlert("连接失败, " + e.getMessage());
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                AlertUtil.showWarnAlert("连接失败");
            }
        }
    }

    @FXML
    void cancel() {
        getDialogStage().close();
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/controller/TableColumnConfigsController.java
================================================
package com.zzg.mybatis.generator.controller;

import com.zzg.mybatis.generator.model.UITableColumnVO;
import com.zzg.mybatis.generator.view.AlertUtil;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.internal.util.JavaBeansUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 定制列配置UI Controller
 *
 * @author xueqi
 * @date 2021-06-24
 */
public class TableColumnConfigsController extends BaseFXController {

	private static final Logger _LOG                  = LoggerFactory.getLogger(TableColumnConfigsController.class);
	private static final String COL_NAME_PREFIX_REGEX = "(?<=%s)[^\"]+";   // pattern regex and split prefix: (?<=aggregate_|f_)[^"]+  f_ or d_ prefix
	private static final String OR_REGEX              = "|";

	@FXML
	private Label     currentTableNameLabel;
	@FXML
	private TextField columnNamePrefixTextLabel;

	private TableView<UITableColumnVO> columnListView;
	private String                     tableName;

	@Override
	public void initialize(URL location, ResourceBundle resources) {
		// do nothing
	}

	@FXML
	public void cancel() {
		this.closeDialogStage();
	}

	@FXML
	public void confirm() {
		try {
			// 1. generator bean propert name
			this.genProertyNameByColumnNamePrefix();

			// close window
			this.closeDialogStage();
		} catch (Exception e) {
			_LOG.error("confirm throw exception.", e);
			AlertUtil.showErrorAlert(e.getMessage());
		}
	}

	public void setColumnListView(TableView<UITableColumnVO> columnListView) {
		this.columnListView = columnListView;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
		currentTableNameLabel.setText(tableName);
	}

	private void genProertyNameByColumnNamePrefix() {
		String columnNamePrefix = this.columnNamePrefixTextLabel.getText();
		if (StringUtils.isNotBlank(columnNamePrefix)) {
			if (StringUtils.endsWith(columnNamePrefix.trim(), OR_REGEX)) {
				columnNamePrefix = StringUtils.removeEnd(columnNamePrefix.trim(), OR_REGEX);
			}

			String regex = String.format(COL_NAME_PREFIX_REGEX, columnNamePrefix);
			_LOG.info("table:{}, column_name_prefix:{}, regex:{}", this.tableName, columnNamePrefix, regex);

			Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);

			ObservableList<UITableColumnVO> items = columnListView.getItems();
			if (CollectionUtils.isNotEmpty(items)) {
				items.stream().forEach(item -> {
					String  columnName = item.getColumnName();
					Matcher matcher    = pattern.matcher(columnName);
					if (matcher.find()) {
						// use first match result
						String regexColumnName = matcher.group();
						if (StringUtils.isNotBlank(regexColumnName)) {
							String propertyName = JavaBeansUtil.getCamelCaseString(regexColumnName, false);
							_LOG.debug("table:{} column_name:{} regex_column_name:{} property_name:{}", tableName, columnName, regexColumnName, propertyName);

							if (StringUtils.isNotBlank(propertyName)) item.setPropertyName(propertyName);
						} else {
							_LOG.warn("table:{} column_name:{} regex_column_name is blank", tableName, columnName);
						}
					} else {
						// if not match, set property name is null
						item.setPropertyName(null);
					}
				});
			}
		}
	}

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/exception/DbDriverLoadingException.java
================================================
package com.zzg.mybatis.generator.exception;

/**
 * 数据库驱动加载异常
 * @Date 2017/8/15 21:46
 * @Author jy
 */
public class DbDriverLoadingException extends RuntimeException{

    public DbDriverLoadingException(String message){
        super(message);
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/model/CachedFXMLLoader.java
================================================
package com.zzg.mybatis.generator.model;

public class CachedFXMLLoader {

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/model/DatabaseConfig.java
================================================
package com.zzg.mybatis.generator.model;

import java.util.Objects;

/**
 * Created by Owen on 5/13/16.
 */
public class DatabaseConfig {

	/**
	 * The primary key in the sqlite db
	 */
	private Integer id;

	private String dbType;
	/**
	 * The name of the config
	 */
	private String name;

	private String host;

	private String port;

	private String schema;

	private String username;

	private String password;

	private String encoding;

    private String lport;

    private String rport;

    private String sshPort;

    private String sshHost;

    private String sshUser;

    private String sshPassword;

    private String privateKeyPassword;

    private String privateKey;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public String getPort() {
		return port;
	}

	public void setPort(String port) {
		this.port = port;
	}

	public String getSchema() {
		return schema;
	}

	public void setSchema(String schema) {
		this.schema = schema;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public String getDbType() {
		return dbType;
	}

	public void setDbType(String dbType) {
		this.dbType = dbType;
	}

    public String getLport() {
        return lport;
    }

    public void setLport(String lport) {
        this.lport = lport;
    }

    public String getRport() {
        return rport;
    }

    public void setRport(String rport) {
        this.rport = rport;
    }

    public String getSshPort() {
        return sshPort;
    }

    public void setSshPort(String sshPort) {
        this.sshPort = sshPort;
    }

    public String getSshHost() {
        return sshHost;
    }

    public void setSshHost(String sshHost) {
        this.sshHost = sshHost;
    }

	public String getSshUser() {
		return sshUser;
	}

	public void setSshUser(String sshUser) {
		this.sshUser = sshUser;
	}

	public String getSshPassword() {
		return sshPassword;
	}

	public void setSshPassword(String sshPassword) {
		this.sshPassword = sshPassword;
	}

	public String getPrivateKeyPassword() {
		return privateKeyPassword;
	}

	public void setPrivateKeyPassword(String privateKeyPassword) {
		this.privateKeyPassword = privateKeyPassword;
	}

	public String getPrivateKey() {
		return privateKey;
	}

	public void setPrivateKey(String privateKey) {
		this.privateKey = privateKey;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		DatabaseConfig that = (DatabaseConfig) o;
		return Objects.equals(id, that.id) &&
			Objects.equals(dbType, that.dbType) &&
			Objects.equals(name, that.name) &&
			Objects.equals(host, that.host) &&
			Objects.equals(port, that.port) &&
			Objects.equals(schema, that.schema) &&
			Objects.equals(username, that.username) &&
			Objects.equals(password, that.password) &&
			Objects.equals(encoding, that.encoding) &&
			Objects.equals(lport, that.lport) &&
			Objects.equals(rport, that.rport) &&
			Objects.equals(sshPort, that.sshPort) &&
			Objects.equals(sshHost, that.sshHost) &&
			Objects.equals(sshUser, that.sshUser) &&
			Objects.equals(sshPassword, that.sshPassword) &&
			Objects.equals(privateKeyPassword, that.privateKeyPassword) &&
			Objects.equals(privateKey, that.privateKey);
	}

	@Override
	public int hashCode() {
		return Objects.hash(id, dbType, name, host, port, schema, username, password, encoding, lport, rport, sshPort, sshHost, sshUser, sshPassword, privateKeyPassword, privateKey);
	}

	@Override
	public String toString() {
		return "DatabaseConfig{" +
				"id=" + id +
				", dbType='" + dbType + '\'' +
				", name='" + name + '\'' +
				", host='" + host + '\'' +
				", port='" + port + '\'' +
				", schema='" + schema + '\'' +
				", username='" + username + '\'' +
				", password='" + password + '\'' +
				", encoding='" + encoding + '\'' +
				", lport='" + lport + '\'' +
				", rport='" + rport + '\'' +
				", sshPort='" + sshPort + '\'' +
				", sshHost='" + sshHost + '\'' +
				", sshUser='" + sshUser + '\'' +
				", sshPassword='" + sshPassword + '\'' +
				'}';
	}
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/model/DatabaseDTO.java
================================================
package com.zzg.mybatis.generator.model;

public class DatabaseDTO {

	private String name;
	private int value;
	private String driverClass;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public String getDriverClass() {
		return driverClass;
	}

	public void setDriverClass(String driverClass) {
		this.driverClass = driverClass;
	}

	@Override
	public String toString() {
		return name;
	}

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/model/DbType.java
================================================
package com.zzg.mybatis.generator.model;

/**
 * Created by Owen on 6/14/16.
 */
public enum DbType {

    MySQL("com.mysql.jdbc.Driver", "jdbc:mysql://%s:%s/%s?useUnicode=true&useSSL=false&characterEncoding=%s", "mysql-connector-java-5.1.38.jar"),
    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"),
    Oracle("oracle.jdbc.OracleDriver", "jdbc:oracle:thin:@//%s:%s/%s", "ojdbc6.jar"),
    PostgreSQL("org.postgresql.Driver", "jdbc:postgresql://%s:%s/%s", "postgresql-9.4.1209.jar"),
	SQL_Server("com.microsoft.sqlserver.jdbc.SQLServerDriver", "jdbc:sqlserver://%s:%s;databaseName=%s", "sqljdbc4-4.0.jar"),
	Sqlite("org.sqlite.JDBC", "jdbc:sqlite:%s", "sqlite-jdbc-3.19.3.jar");

    private final String driverClass;
    private final String connectionUrlPattern;
    private final String connectorJarFile;

    DbType(String driverClass, String connectionUrlPattern, String connectorJarFile) {
        this.driverClass = driverClass;
        this.connectionUrlPattern = connectionUrlPattern;
        this.connectorJarFile = connectorJarFile;
    }

    public String getDriverClass() {
        return driverClass;
    }

    public String getConnectionUrlPattern() {
        return connectionUrlPattern;
    }

    public String getConnectorJarFile() {
        return connectorJarFile;
    }
}

================================================
FILE: src/main/java/com/zzg/mybatis/generator/model/GeneratorConfig.java
================================================
package com.zzg.mybatis.generator.model;

/**
 *
 * GeneratorConfig is the Config of mybatis generator config exclude database
 * config
 *
 * Created by Owen on 6/16/16.
 */
public class GeneratorConfig {

	/**
	 * 本配置的名称
	 */
	private String name;

	private String connectorJarPath;

	private String projectFolder;

	private String modelPackage;

	private String modelPackageTargetFolder;

	private String daoPackage;

	private String daoTargetFolder;

	private String mapperName;

	private String mappingXMLPackage;

	private String mappingXMLTargetFolder;

	private String tableName;

	private String domainObjectName;

	private boolean offsetLimit;

	private boolean comment;

	private boolean overrideXML;

	private boolean needToStringHashcodeEquals;

	private boolean useLombokPlugin;

	private boolean needForUpdate;

	private boolean annotationDAO;

	private boolean annotation;

	private boolean useActualColumnNames;

	private boolean useExample;

	private String generateKeys;

	private String encoding;

	private boolean useTableNameAlias;

	private boolean useDAOExtendStyle;

    private boolean useSchemaPrefix;

    private boolean jsr310Support;

    public boolean isJsr310Support() {
        return jsr310Support;
    }

    public void setJsr310Support(boolean jsr310Support) {
        this.jsr310Support = jsr310Support;
    }

    public boolean isUseSchemaPrefix() {
        return useSchemaPrefix;
    }

    public void setUseSchemaPrefix(boolean useSchemaPrefix) {
        this.useSchemaPrefix = useSchemaPrefix;
    }

	public boolean isUseExample() {
		return useExample;
	}

	public void setUseExample(boolean useExample) {
		this.useExample = useExample;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public String getDomainObjectName() {
		return domainObjectName;
	}

	public void setDomainObjectName(String domainObjectName) {
		this.domainObjectName = domainObjectName;
	}

	public String getConnectorJarPath() {
		return connectorJarPath;
	}

	public void setConnectorJarPath(String connectorJarPath) {
		this.connectorJarPath = connectorJarPath;
	}

	public String getProjectFolder() {
		return projectFolder;
	}

	public void setProjectFolder(String projectFolder) {
		this.projectFolder = projectFolder;
	}

	public String getModelPackage() {
		return modelPackage;
	}

	public void setModelPackage(String modelPackage) {
		this.modelPackage = modelPackage;
	}

	public String getModelPackageTargetFolder() {
		return modelPackageTargetFolder;
	}

	public void setModelPackageTargetFolder(String modelPackageTargetFolder) {
		this.modelPackageTargetFolder = modelPackageTargetFolder;
	}

	public String getDaoPackage() {
		return daoPackage;
	}

	public void setDaoPackage(String daoPackage) {
		this.daoPackage = daoPackage;
	}

	public String getDaoTargetFolder() {
		return daoTargetFolder;
	}

	public void setDaoTargetFolder(String daoTargetFolder) {
		this.daoTargetFolder = daoTargetFolder;
	}

	public String getMappingXMLPackage() {
		return mappingXMLPackage;
	}

	public void setMappingXMLPackage(String mappingXMLPackage) {
		this.mappingXMLPackage = mappingXMLPackage;
	}

	public String getMappingXMLTargetFolder() {
		return mappingXMLTargetFolder;
	}

	public void setMappingXMLTargetFolder(String mappingXMLTargetFolder) {
		this.mappingXMLTargetFolder = mappingXMLTargetFolder;
	}

	public boolean isOffsetLimit() {
		return offsetLimit;
	}

	public void setOffsetLimit(boolean offsetLimit) {
		this.offsetLimit = offsetLimit;
	}

	public boolean isComment() {
		return comment;
	}

	public void setComment(boolean comment) {
		this.comment = comment;
	}

    public boolean isNeedToStringHashcodeEquals() {
        return needToStringHashcodeEquals;
    }

    public void setNeedToStringHashcodeEquals(boolean needToStringHashcodeEquals) {
        this.needToStringHashcodeEquals = needToStringHashcodeEquals;
    }

	public boolean isUseLombokPlugin() {
		return useLombokPlugin;
	}

	public void setUseLombokPlugin(boolean useLombokPlugin) {
		this.useLombokPlugin = useLombokPlugin;
	}

	public boolean isNeedForUpdate() {
		return needForUpdate;
	}

	public void setNeedForUpdate(boolean needForUpdate) {
		this.needForUpdate = needForUpdate;
	}

	public boolean isAnnotationDAO() {
		return annotationDAO;
	}

	public void setAnnotationDAO(boolean annotationDAO) {
		this.annotationDAO = annotationDAO;
	}

	public boolean isAnnotation() {
		return annotation;
	}

	public void setAnnotation(boolean annotation) {
		this.annotation = annotation;
	}

	public boolean isUseActualColumnNames() {
		return useActualColumnNames;
	}

	public void setUseActualColumnNames(boolean useActualColumnNames) {
		this.useActualColumnNames = useActualColumnNames;
	}

	public String getMapperName() {
		return mapperName;
	}

	public void setMapperName(String mapperName) {
		this.mapperName = mapperName;
	}

	public String getGenerateKeys() {
		return generateKeys;
	}

	public void setGenerateKeys(String generateKeys) {
		this.generateKeys = generateKeys;
	}

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

	public boolean getUseTableNameAlias() {
		return useTableNameAlias;
	}

	public void setUseTableNameAlias(boolean useTableNameAlias) {
		this.useTableNameAlias = useTableNameAlias;
	}

	public boolean isUseTableNameAlias() {
		return useTableNameAlias;
	}

	public boolean isOverrideXML() {
		return overrideXML;
	}

	public void setOverrideXML(boolean overrideXML) {
		this.overrideXML = overrideXML;
	}

	public void setUseDAOExtendStyle(boolean useDAOExtendStyle) {
		this.useDAOExtendStyle = useDAOExtendStyle;
	}

	public boolean isUseDAOExtendStyle() {
		return useDAOExtendStyle;
	}
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/model/UITableColumnVO.java
================================================
package com.zzg.mybatis.generator.model;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 * Created by Owen on 6/22/16.
 */
public class UITableColumnVO {

    private BooleanProperty checked = new SimpleBooleanProperty(true); // Default set to true

    private StringProperty columnName = new SimpleStringProperty();

    private StringProperty javaType = new SimpleStringProperty();

    private StringProperty jdbcType = new SimpleStringProperty();

    private StringProperty propertyName = new SimpleStringProperty();

    private StringProperty typeHandle = new SimpleStringProperty();

    public String getColumnName() {
        return columnName.get();
    }

    public void setColumnName(String columnName) {
        this.columnName.set(columnName);
    }

    public String getJdbcType() {
        return jdbcType.get();
    }

    public void setJdbcType(String jdbcType) {
        this.jdbcType.set(jdbcType);
    }

    public String getPropertyName() {
        return propertyName.get();
    }

    public void setPropertyName(String propertyName) {
        this.propertyName.set(propertyName);
    }

    public BooleanProperty checkedProperty() {
        return checked;
    }

    public Boolean getChecked() {
        return this.checked.get();
    }

    public void setChecked(Boolean checked) {
        this.checked.set(checked);
    }

    public StringProperty typeHandleProperty() {
        return typeHandle;
    }

    public String getTypeHandle() {
        return typeHandle.get();
    }

    public void setTypeHandle(String typeHandle) {
        this.typeHandle.set(typeHandle);
    }

    public StringProperty columnNameProperty() {
        return columnName;
    }

    public StringProperty jdbcTypeProperty() {
        return jdbcType;
    }

    public StringProperty propertyNameProperty() {
        return propertyName;
    }

    public String getJavaType() {
        return javaType.get();
    }

    public StringProperty javaTypeProperty() {
        return javaType;
    }

    public void setJavaType(String javaType) {
        this.javaType.set(javaType);
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/plugins/CommonDAOInterfacePlugin.java
================================================
package com.zzg.mybatis.generator.plugins;

import org.mybatis.generator.api.*;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.exception.ShellException;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;

/**
 * Project: mybatis-generator-gui
 *
 * @author slankka on 2018/3/11.
 */
public class CommonDAOInterfacePlugin extends PluginAdapter {

    private static final String DEFAULT_DAO_SUPER_CLASS = ".MyBatisBaseDao";
    private static final FullyQualifiedJavaType SERIALIZEBLE_TYPE = new FullyQualifiedJavaType("java.io.Serializable");

    private List<Method> methods = new ArrayList<>();

    private ShellCallback shellCallback = null;

    public CommonDAOInterfacePlugin() {
        shellCallback = new DefaultShellCallback(false);
    }
    
    private boolean isUseExample() {
    	return "true".equals(getProperties().getProperty("useExample"));
	}

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        boolean hasPk = introspectedTable.hasPrimaryKeyColumns();
        JavaFormatter javaFormatter = context.getJavaFormatter();
        String daoTargetDir = context.getJavaClientGeneratorConfiguration().getTargetProject();
        String daoTargetPackage = context.getJavaClientGeneratorConfiguration().getTargetPackage();
        List<GeneratedJavaFile> mapperJavaFiles = new ArrayList<>();
        String javaFileEncoding = context.getProperty("javaFileEncoding");
        Interface mapperInterface = new Interface(daoTargetPackage + DEFAULT_DAO_SUPER_CLASS);

        if (stringHasValue(daoTargetPackage)) {
            mapperInterface.addImportedType(SERIALIZEBLE_TYPE);

            mapperInterface.setVisibility(JavaVisibility.PUBLIC);
            mapperInterface.addJavaDocLine("/**");
            mapperInterface.addJavaDocLine(" * " + "DAO公共基类,由MybatisGenerator自动生成请勿修改");
            mapperInterface.addJavaDocLine(" * " + "@param <Model> The Model Class 这里是泛型不是Model类");
            mapperInterface.addJavaDocLine(" * " + "@param <PK> The Primary Key Class 如果是无主键,则可以用Model来跳过,如果是多主键则是Key类");
			if (isUseExample()) {
				mapperInterface.addJavaDocLine(" * " + "@param <E> The Example Class");
			}
            mapperInterface.addJavaDocLine(" */");

            FullyQualifiedJavaType daoBaseInterfaceJavaType = mapperInterface.getType();
            daoBaseInterfaceJavaType.addTypeArgument(new FullyQualifiedJavaType("Model"));
            daoBaseInterfaceJavaType.addTypeArgument(new FullyQualifiedJavaType("PK extends Serializable"));
			if (isUseExample()) {
				daoBaseInterfaceJavaType.addTypeArgument(new FullyQualifiedJavaType("E"));
			}

            if (!this.methods.isEmpty()) {
                for (Method method : methods) {
                    mapperInterface.addMethod(method);
                }
            }

            List<GeneratedJavaFile> generatedJavaFiles = introspectedTable.getGeneratedJavaFiles();
            for (GeneratedJavaFile generatedJavaFile : generatedJavaFiles) {
                CompilationUnit compilationUnit = generatedJavaFile.getCompilationUnit();
                FullyQualifiedJavaType type = compilationUnit.getType();
                String modelName = type.getShortName();
                if (modelName.endsWith("DAO")) {
                }
            }
            GeneratedJavaFile mapperJavafile = new GeneratedJavaFile(mapperInterface, daoTargetDir, javaFileEncoding, javaFormatter);
            try {
                File mapperDir = shellCallback.getDirectory(daoTargetDir, daoTargetPackage);
                File mapperFile = new File(mapperDir, mapperJavafile.getFileName());
                // 文件不存在
                if (!mapperFile.exists()) {
                    mapperJavaFiles.add(mapperJavafile);
                }
            } catch (ShellException e) {
                e.printStackTrace();
            }
        }
        return mapperJavaFiles;
    }

    @Override
    public boolean clientGenerated(Interface interfaze,
                                   TopLevelClass topLevelClass,
                                   IntrospectedTable introspectedTable) {
        interfaze.addJavaDocLine("/**");
        interfaze.addJavaDocLine(" * " + interfaze.getType().getShortName() + "继承基类");
        interfaze.addJavaDocLine(" */");

        String daoSuperClass = interfaze.getType().getPackageName() + DEFAULT_DAO_SUPER_CLASS;
        FullyQualifiedJavaType daoSuperType = new FullyQualifiedJavaType(daoSuperClass);

        String targetPackage = introspectedTable.getContext().getJavaModelGeneratorConfiguration().getTargetPackage();

        String domainObjectName = introspectedTable.getTableConfiguration().getDomainObjectName();
        FullyQualifiedJavaType baseModelJavaType = new FullyQualifiedJavaType(targetPackage + "." + domainObjectName);
        daoSuperType.addTypeArgument(baseModelJavaType);

        FullyQualifiedJavaType primaryKeyTypeJavaType = null;
        if (introspectedTable.getPrimaryKeyColumns().size() > 1) {
            primaryKeyTypeJavaType = new FullyQualifiedJavaType(targetPackage + "." + domainObjectName + "Key");
        }else if(introspectedTable.hasPrimaryKeyColumns()){
            primaryKeyTypeJavaType = introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType();
        }else {
            primaryKeyTypeJavaType = baseModelJavaType;
        }
        daoSuperType.addTypeArgument(primaryKeyTypeJavaType);
		interfaze.addImportedType(primaryKeyTypeJavaType);

		if (isUseExample()) {
			String exampleType = introspectedTable.getExampleType();
			FullyQualifiedJavaType exampleTypeJavaType = new FullyQualifiedJavaType(exampleType);
			daoSuperType.addTypeArgument(exampleTypeJavaType);
			interfaze.addImportedType(exampleTypeJavaType);
		}
        interfaze.addImportedType(baseModelJavaType);
        interfaze.addImportedType(daoSuperType);
        interfaze.addSuperInterface(daoSuperType);
        return true;
    }

    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    private void interceptExampleParam(Method method) {
		if (isUseExample()) {
			method.getParameters().clear();
			method.addParameter(new Parameter(new FullyQualifiedJavaType("E"), "example"));
			methods.add(method);
		}
    }

    private void interceptPrimaryKeyParam(Method method) {
        method.getParameters().clear();
        method.addParameter(new Parameter(new FullyQualifiedJavaType("PK"), "id"));
        methods.add(method);
    }

    private void interceptModelParam(Method method) {
        method.getParameters().clear();
        method.addParameter(new Parameter(new FullyQualifiedJavaType("Model"), "record"));
        methods.add(method);
    }

    private void interceptModelAndExampleParam(Method method) {
		if (isUseExample()) {
			List<Parameter> parameters = method.getParameters();
			if (parameters.size() == 1) {
				interceptExampleParam(method);
			}else{
				method.getParameters().clear();
				Parameter parameter1 = new Parameter(new FullyQualifiedJavaType("Model"), "record");
				parameter1.addAnnotation("@Param(\"record\")");
				method.addParameter(parameter1);

				Parameter parameter2 = new Parameter(new FullyQualifiedJavaType("E"), "example");
				parameter2.addAnnotation("@Param(\"example\")");
				method.addParameter(parameter2);
				methods.add(method);
			}
		}
    }

    @Override
    public boolean clientCountByExampleMethodGenerated(Method method,
                                                       Interface interfaze, IntrospectedTable introspectedTable) {
//        interface
		if (isUseExample()) {
			interceptExampleParam(method);
		}
		return false;
	}


    @Override
    public boolean clientDeleteByExampleMethodGenerated(Method method,
                                                        Interface interfaze, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptExampleParam(method);
		}
        return false;
    }


    @Override
    public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method,
                                                           Interface interfaze, IntrospectedTable introspectedTable) {
    	interceptPrimaryKeyParam(method);
        return false;
    }

    @Override
    public boolean clientInsertMethodGenerated(Method method, Interface interfaze,
                                                  IntrospectedTable introspectedTable) {
        interceptModelParam(method);
        return false;
    }

    @Override
    public boolean clientSelectByExampleWithBLOBsMethodGenerated(Method method,
                                                                 Interface interfaze, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptExampleParam(method);
			method.setReturnType(new FullyQualifiedJavaType("List<Model>"));
		}
        return false;
    }

    @Override
    public boolean clientSelectByExampleWithoutBLOBsMethodGenerated(Method method,
                                                                    Interface interfaze, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptExampleParam(method);
			method.setReturnType(new FullyQualifiedJavaType("List<Model>"));
		}
        return false;
    }

    @Override
    public boolean clientSelectByPrimaryKeyMethodGenerated(Method method,
                                                           Interface interfaze, IntrospectedTable introspectedTable) {
    	interceptPrimaryKeyParam(method);
        method.setReturnType(new FullyQualifiedJavaType("Model"));
        return false;
    }

    @Override
    public boolean clientUpdateByExampleSelectiveMethodGenerated(Method method,
                                                                 Interface interfaze, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptModelAndExampleParam(method);
		}
        return false;
    }

    @Override
    public boolean clientUpdateByExampleWithBLOBsMethodGenerated(Method method,
                                                                 Interface interfaze, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptModelAndExampleParam(method);
		}
        return false;
    }

    @Override
    public boolean clientUpdateByExampleWithoutBLOBsMethodGenerated(Method method,
                                                                    Interface interfaze, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptModelAndExampleParam(method);
		}
        return false;
    }

    @Override
    public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method,
                                                                    Interface interfaze, IntrospectedTable introspectedTable) {
        interceptModelParam(method);
        return false;
    }

    @Override
    public boolean clientUpdateByExampleWithoutBLOBsMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptModelAndExampleParam(method);
		}
        return false;
    }

    @Override
    public boolean clientUpdateByExampleSelectiveMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        if (isUseExample()) {
			interceptModelAndExampleParam(method);
		}
        return false;
    }

    @Override
    public boolean clientUpdateByPrimaryKeyWithBLOBsMethodGenerated(Method method,
                                                                    Interface interfaze, IntrospectedTable introspectedTable) {
    	interceptModelParam(method);
        return false;
    }

    @Override
    public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated(
            Method method, Interface interfaze,
            IntrospectedTable introspectedTable) {
        interceptModelParam(method);
        return false;
    }

    @Override
    public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        interceptModelParam(method);
        return false;
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/plugins/DbRemarksCommentGenerator.java
================================================
/*
 *  Copyright 2008 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.zzg.mybatis.generator.plugins;

import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.internal.util.StringUtility;

import java.util.Properties;
import java.util.Set;

import static org.mybatis.generator.internal.util.StringUtility.isTrue;

/**
 * 此插件使用数据库表中列的注释来生成Java Model中属性的注释
 *
 * @author Owen Zou
 * 
 */
public class DbRemarksCommentGenerator implements CommentGenerator {


    private Properties properties;
    private boolean columnRemarks;
    private boolean isAnnotations;

    public DbRemarksCommentGenerator() {
        super();
        properties = new Properties();
    }


    public void addJavaFileComment(CompilationUnit compilationUnit) {
        // add no file level comments by default
        if (isAnnotations) {
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.Table"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.Id"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.Column"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("javax.persistence.GeneratedValue"));
            compilationUnit.addImportedType(new FullyQualifiedJavaType("org.hibernate.validator.constraints.NotEmpty"));
        }
    }

    /**
     * Adds a suitable comment to warn users that the element was generated, and
     * when it was generated.
     */
    public void addComment(XmlElement xmlElement) {
    }

    public void addRootComment(XmlElement rootElement) {
        // add no document level comments by default
        return;
    }

	@Override
	public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> set) {


	}

	@Override
	public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> set) {

	}

	@Override
	public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> set) {

	}

	@Override
	public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> set) {

	}

	@Override
	public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable, Set<FullyQualifiedJavaType> set) {
	}

	public void addConfigurationProperties(Properties properties) {
        this.properties.putAll(properties);
        columnRemarks = isTrue(properties
                .getProperty("columnRemarks"));
        isAnnotations = isTrue(properties
                .getProperty("annotations"));
    }

    public void addClassComment(InnerClass innerClass,
            IntrospectedTable introspectedTable) {
    }

    public void addModelClassComment(TopLevelClass topLevelClass,
                                IntrospectedTable introspectedTable) {
        topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine(" * @author ");
        topLevelClass.addJavaDocLine(" * " + introspectedTable.getRemarks());
        topLevelClass.addJavaDocLine(" */");
        if(isAnnotations) {
            topLevelClass.addAnnotation("@Table(name=\"" + introspectedTable.getFullyQualifiedTableNameAtRuntime() + "\")");
        }
    }

    public void addEnumComment(InnerEnum innerEnum,
            IntrospectedTable introspectedTable) {
    }

    public void addFieldComment(Field field,
            IntrospectedTable introspectedTable,
            IntrospectedColumn introspectedColumn) {
        if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) {
            field.addJavaDocLine("/**");
            StringBuilder sb = new StringBuilder();
            sb.append(" * ");
            sb.append(introspectedColumn.getRemarks());
            field.addJavaDocLine(sb.toString());
            field.addJavaDocLine(" */");
        }

        if (isAnnotations) {
            boolean isId = false;
            for (IntrospectedColumn column : introspectedTable.getPrimaryKeyColumns()) {
                if (introspectedColumn == column) {
                    isId = true;
                    field.addAnnotation("@Id");
                    field.addAnnotation("@GeneratedValue");
                    break;
                }
            }
            if (!introspectedColumn.isNullable() && !isId){
                field.addAnnotation("@NotEmpty");
            }
            if (introspectedColumn.isIdentity()) {
                if (introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement().equals("JDBC")) {
                    field.addAnnotation("@GeneratedValue(generator = \"JDBC\")");
                } else {
                    field.addAnnotation("@GeneratedValue(strategy = GenerationType.IDENTITY)");
                }
            } else if (introspectedColumn.isSequenceColumn()) {
                field.addAnnotation("@SequenceGenerator(name=\"\",sequenceName=\"" + introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement() + "\")");
            }
        }
    }

    public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
    }

    public void addGeneralMethodComment(Method method,
            IntrospectedTable introspectedTable) {
    }

    public void addGetterComment(Method method,
            IntrospectedTable introspectedTable,
            IntrospectedColumn introspectedColumn) {
    }

    public void addSetterComment(Method method,
            IntrospectedTable introspectedTable,
            IntrospectedColumn introspectedColumn) {
    }

    public void addClassComment(InnerClass innerClass,
            IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
        innerClass.addJavaDocLine("/**"); //$NON-NLS-1$
        innerClass.addJavaDocLine(" */"); //$NON-NLS-1$
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/plugins/JavaTypeResolverJsr310Impl.java
================================================
package com.zzg.mybatis.generator.plugins;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl;

import java.sql.Types;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @author hanakei
 * @since 2018/4/28
 */
public class JavaTypeResolverJsr310Impl extends JavaTypeResolverDefaultImpl {

    @Override
    protected FullyQualifiedJavaType overrideDefaultType(IntrospectedColumn column, FullyQualifiedJavaType defaultType) {
        FullyQualifiedJavaType answer = defaultType;

        switch (column.getJdbcType()) {
            case Types.BIT:
                answer = calculateBitReplacement(column, defaultType);
                break;
            case Types.DECIMAL:
            case Types.NUMERIC:
                answer = calculateBigDecimalReplacement(column, defaultType);
                break;
            case Types.DATE:
                answer = new FullyQualifiedJavaType(LocalDate.class.getName());
                break;
            case Types.TIME:
                answer = new FullyQualifiedJavaType(LocalTime.class.getName());
                break;
            case Types.TIMESTAMP:
                answer = new FullyQualifiedJavaType(LocalDateTime.class.getName());
                break;
            default:
                break;
        }

        return answer;
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/plugins/MySQLForUpdatePlugin.java
================================================
package com.zzg.mybatis.generator.plugins;

import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;

import java.util.List;

/**
 * Project: mybatis-generator-gui
 *
 * @author slankka on 2017/11/4.
 */
public class MySQLForUpdatePlugin extends PluginAdapter {

    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

        PrimitiveTypeWrapper booleanWrapper = FullyQualifiedJavaType.getBooleanPrimitiveInstance().getPrimitiveTypeWrapper();
        Field forUpdate = new Field();
        forUpdate.setName("forUpdate");
        forUpdate.setVisibility(JavaVisibility.PRIVATE);
        forUpdate.setType(booleanWrapper);
        topLevelClass.addField(forUpdate);

        Method setForUpdate = new Method();
        setForUpdate.setVisibility(JavaVisibility.PUBLIC);
        setForUpdate.setName("setForUpdate");
        setForUpdate.addParameter(new Parameter(booleanWrapper, "forUpdate"));
        setForUpdate.addBodyLine("this.forUpdate = forUpdate;");
        topLevelClass.addMethod(setForUpdate);

        Method getForUpdate = new Method();
        getForUpdate.setVisibility(JavaVisibility.PUBLIC);
        getForUpdate.setReturnType(booleanWrapper);
        getForUpdate.setName("getForUpdate");
        getForUpdate.addBodyLine("return forUpdate;");
        topLevelClass.addMethod(getForUpdate);

        return true;
    }

    private void appendForUpdate(XmlElement element, IntrospectedTable introspectedTable) {
        XmlElement forUpdateElement = new XmlElement("if");
        forUpdateElement.addAttribute(new Attribute("test", "forUpdate != null and forUpdate == true"));
        forUpdateElement.addElement(new TextElement("for update"));
        element.addElement(forUpdateElement);
    }


    @Override
    public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        appendForUpdate(element, introspectedTable);
        return true;
    }

    @Override
    public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        appendForUpdate(element, introspectedTable);
        return true;
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/plugins/MySQLLimitPlugin.java
================================================
package com.zzg.mybatis.generator.plugins;

/**
 * Created by zouzhigang on 2016/6/14.
 */

import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;

import java.util.List;

public class MySQLLimitPlugin extends PluginAdapter {

    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    /**
     * 为每个Example类添加limit和offset属性已经set、get方法
     */
    @Override
    public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

        PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper();
        PrimitiveTypeWrapper longWrapper = new FullyQualifiedJavaType("long").getPrimitiveTypeWrapper();

        Field limit = new Field();
        limit.setName("limit");
        limit.setVisibility(JavaVisibility.PRIVATE);
        limit.setType(integerWrapper);
        topLevelClass.addField(limit);

        Method setLimit = new Method();
        setLimit.setVisibility(JavaVisibility.PUBLIC);
        setLimit.setName("setLimit");
        setLimit.addParameter(new Parameter(integerWrapper, "limit"));
        setLimit.addBodyLine("this.limit = limit;");
        topLevelClass.addMethod(setLimit);

        Method getLimit = new Method();
        getLimit.setVisibility(JavaVisibility.PUBLIC);
        getLimit.setReturnType(integerWrapper);
        getLimit.setName("getLimit");
        getLimit.addBodyLine("return limit;");
        topLevelClass.addMethod(getLimit);

        Field offset = new Field();
        offset.setName("offset");
        offset.setVisibility(JavaVisibility.PRIVATE);
        offset.setType(longWrapper);
        topLevelClass.addField(offset);

        Method setOffset = new Method();
        setOffset.setVisibility(JavaVisibility.PUBLIC);
        setOffset.setName("setOffset");
        setOffset.addParameter(new Parameter(longWrapper, "offset"));
        setOffset.addBodyLine("this.offset = offset;");
        topLevelClass.addMethod(setOffset);

        Method getOffset = new Method();
        getOffset.setVisibility(JavaVisibility.PUBLIC);
        getOffset.setReturnType(longWrapper);
        getOffset.setName("getOffset");
        getOffset.addBodyLine("return offset;");
        topLevelClass.addMethod(getOffset);

        return true;
    }

    /**
     * 为Mapper.xml的selectByExample添加limit
     */
    @Override
    public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element,
                                                                     IntrospectedTable introspectedTable) {

        XmlElement ifLimitNotNullElement = new XmlElement("if");
        ifLimitNotNullElement.addAttribute(new Attribute("test", "limit != null"));

        XmlElement ifOffsetNotNullElement = new XmlElement("if");
        ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null"));
        ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${limit}"));
        ifLimitNotNullElement.addElement(ifOffsetNotNullElement);

        XmlElement ifOffsetNullElement = new XmlElement("if");
        ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null"));
        ifOffsetNullElement.addElement(new TextElement("limit ${limit}"));
        ifLimitNotNullElement.addElement(ifOffsetNullElement);

        element.addElement(ifLimitNotNullElement);

        return true;
    }

    /**
     * 为Mapper.xml的selectByExampleWithBLOBs添加limit
     */
    @Override
    public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {
        XmlElement ifLimitNotNullElement = new XmlElement("if");
        ifLimitNotNullElement.addAttribute(new Attribute("test", "limit != null"));

        XmlElement ifOffsetNotNullElement = new XmlElement("if");
        ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null"));
        ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${limit}"));
        ifLimitNotNullElement.addElement(ifOffsetNotNullElement);

        XmlElement ifOffsetNullElement = new XmlElement("if");
        ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null"));
        ifOffsetNullElement.addElement(new TextElement("limit ${limit}"));
        ifLimitNotNullElement.addElement(ifOffsetNullElement);

        element.addElement(ifLimitNotNullElement);

        return true;
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/plugins/RepositoryPlugin.java
================================================
package com.zzg.mybatis.generator.plugins;

import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;

import java.util.List;

/**
 * Project: mybatis-generator-gui
 *
 * @author slankka on 2017/12/13.
 */
public class RepositoryPlugin extends PluginAdapter {

    private FullyQualifiedJavaType annotationRepository;
    private String annotation = "@Repository";

    public RepositoryPlugin () {
        annotationRepository = new FullyQualifiedJavaType("org.springframework.stereotype.Repository"); //$NON-NLS-1$
    }

    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        interfaze.addImportedType(annotationRepository);
        interfaze.addAnnotation(annotation);
        return true;
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/util/ConfigHelper.java
================================================
package com.zzg.mybatis.generator.util;

import com.alibaba.fastjson.JSON;
import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.model.DbType;
import com.zzg.mybatis.generator.model.GeneratorConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * XML based config file help class
 * <p>
 * Created by Owen on 6/16/16.
 */
public class ConfigHelper {

	private static final Logger _LOG = LoggerFactory.getLogger(ConfigHelper.class);
	private static final String BASE_DIR = "config";
	private static final String CONFIG_FILE = "/sqlite3.db";

	public static void createEmptyFiles() throws Exception {
		File file = new File(BASE_DIR);
		if (!file.exists()) {
			file.mkdir();
		}
		File uiConfigFile = new File(BASE_DIR + CONFIG_FILE);
		if (!uiConfigFile.exists()) {
			createEmptyXMLFile(uiConfigFile);
		}
	}

	static void createEmptyXMLFile(File uiConfigFile) throws IOException {
		InputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = Thread.currentThread().getContextClassLoader().getResourceAsStream("sqlite3.db");
			fos = new FileOutputStream(uiConfigFile);
			byte[] buffer = new byte[1024];
			int byteread = 0;
			while ((byteread = fis.read(buffer)) != -1) {
				fos.write(buffer, 0, byteread);
			}
		} finally {
			if (fis != null) fis.close();
			if (fos != null) fos.close();
		}

	}

	public static List<DatabaseConfig> loadDatabaseConfig() throws Exception {
		Connection conn = null;
		Statement stat = null;
		ResultSet rs = null;
		try {
			conn = ConnectionManager.getConnection();
			stat = conn.createStatement();
			rs = stat.executeQuery("SELECT * FROM dbs");
			List<DatabaseConfig> configs = new ArrayList<>();
			while (rs.next()) {
				int id = rs.getInt("id");
				String value = rs.getString("value");
				DatabaseConfig databaseConfig = JSON.parseObject(value, DatabaseConfig.class);
				databaseConfig.setId(id);
				configs.add(databaseConfig);
			}

			return configs;
		} finally {
			if (rs != null) rs.close();
			if (stat != null) stat.close();
			if (conn != null) conn.close();
		}
	}

	public static void saveDatabaseConfig(boolean isUpdate, Integer primaryKey, DatabaseConfig dbConfig) throws Exception {
		String configName = dbConfig.getName();
		Connection conn = null;
		Statement stat = null;
		ResultSet rs = null;
		try {
			conn = ConnectionManager.getConnection();
			stat = conn.createStatement();
			if (!isUpdate) {
				ResultSet rs1 = stat.executeQuery("SELECT * from dbs where name = '" + configName + "'");
				if (rs1.next()) {
					throw new RuntimeException("配置已经存在, 请使用其它名字");
				}
			}
			String jsonStr = JSON.toJSONString(dbConfig);
			String sql;
			if (isUpdate) {
				sql = String.format("UPDATE dbs SET name = '%s', value = '%s' where id = %d", configName, jsonStr, primaryKey);
			} else {
				sql = String.format("INSERT INTO dbs (name, value) values('%s', '%s')", configName, jsonStr);
			}
			stat.executeUpdate(sql);
		} finally {
			if (rs != null) rs.close();
			if (stat != null) stat.close();
			if (conn != null) conn.close();
		}
	}

	public static void deleteDatabaseConfig(DatabaseConfig databaseConfig) throws Exception {
		Connection conn = null;
		Statement stat = null;
		ResultSet rs = null;
		try {
			conn = ConnectionManager.getConnection();
			stat = conn.createStatement();
			String sql = String.format("delete from dbs where id=%d", databaseConfig.getId());
			stat.executeUpdate(sql);
		} finally {
			if (rs != null) rs.close();
			if (stat != null) stat.close();
			if (conn != null) conn.close();
		}
	}

	public static void saveGeneratorConfig(GeneratorConfig generatorConfig) throws Exception {
		Connection conn = null;
		Statement stat = null;
		ResultSet rs = null;
		try {
			conn = ConnectionManager.getConnection();
			stat = conn.createStatement();
			String jsonStr = JSON.toJSONString(generatorConfig);
			String sql = String.format("INSERT INTO generator_config values('%s', '%s')", generatorConfig.getName(),
					jsonStr);
			stat.executeUpdate(sql);
		} finally {
			if (rs != null) rs.close();
			if (stat != null) stat.close();
			if (conn != null) conn.close();
		}
	}

	public static GeneratorConfig loadGeneratorConfig(String name) throws Exception {
		Connection conn = null;
		Statement stat = null;
		ResultSet rs = null;
		try {
			conn = ConnectionManager.getConnection();
			stat = conn.createStatement();
			String sql = String.format("SELECT * FROM generator_config where name='%s'", name);
			_LOG.info("sql: {}", sql);
			rs = stat.executeQuery(sql);
			GeneratorConfig generatorConfig = null;
			if (rs.next()) {
				String value = rs.getString("value");
				generatorConfig = JSON.parseObject(value, GeneratorConfig.class);
			}
			return generatorConfig;
		} finally {
			if (rs != null) rs.close();
			if (stat != null) stat.close();
			if (conn != null) conn.close();
		}
	}

	public static List<GeneratorConfig> loadGeneratorConfigs() throws Exception {
		Connection conn = null;
		Statement stat = null;
		ResultSet rs = null;
		try {
			conn = ConnectionManager.getConnection();
			stat = conn.createStatement();
			String sql = String.format("SELECT * FROM generator_config");
			_LOG.info("sql: {}", sql);
			rs = stat.executeQuery(sql);
			List<GeneratorConfig> configs = new ArrayList<>();
			while (rs.next()) {
				String value = rs.getString("value");
				configs.add(JSON.parseObject(value, GeneratorConfig.class));
			}
			return configs;
		} finally {
			if (rs != null) rs.close();
			if (stat != null) stat.close();
			if (conn != null) conn.close();
		}
	}

	public static int deleteGeneratorConfig(String name) throws Exception {
		Connection conn = null;
		Statement stat = null;
		try {
			conn = ConnectionManager.getConnection();
			stat = conn.createStatement();
			String sql = String.format("DELETE FROM generator_config where name='%s'", name);
			_LOG.info("sql: {}", sql);
			return stat.executeUpdate(sql);
		} finally {
			if (stat != null) stat.close();
			if (conn != null) conn.close();
		}
	}

	public static String findConnectorLibPath(String dbType) {
		DbType type = DbType.valueOf(dbType);
		URL resource = Thread.currentThread().getContextClassLoader().getResource("logback.xml");
		_LOG.info("jar resource: {}", resource);
		if (resource != null) {
			try {
				File file = new File(resource.toURI().getRawPath() + "/../lib/" + type.getConnectorJarFile());
				return URLDecoder.decode(file.getCanonicalPath(), Charset.forName("UTF-8").displayName());
			} catch (Exception e) {
				throw new RuntimeException("找不到驱动文件,请联系开发者");
			}
		} else {
			throw new RuntimeException("lib can't find");
		}
	}

	public static List<String> getAllJDBCDriverJarPaths() {
		List<String> jarFilePathList = new ArrayList<>();
		URL url = Thread.currentThread().getContextClassLoader().getResource("logback.xml");
		try {
			File file;
			if (url.getPath().contains(".jar")) {
				file = new File("lib/");
			} else {
				file = new File("src/main/resources/lib");
			}
			_LOG.info("jar lib path: {}", file.getCanonicalPath());
			File[] jarFiles = file.listFiles();
			if (jarFiles != null && jarFiles.length > 0) {
				for (File jarFile : jarFiles) {
					_LOG.info("jar file: {}", jarFile.getAbsolutePath());
					if (jarFile.isFile() && jarFile.getAbsolutePath().endsWith(".jar")) {
						jarFilePathList.add(jarFile.getAbsolutePath());
					}
				}
			}
		} catch (Exception e) {
			throw new RuntimeException("找不到驱动文件,请联系开发者");
		}
		return jarFilePathList;
	}


}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/util/ConnectionManager.java
================================================
package com.zzg.mybatis.generator.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;

/**
 * Created by Owen on 8/21/16.
 */
public class ConnectionManager {
    private static final Logger _LOG = LoggerFactory.getLogger(ConnectionManager.class);
    private static final String DB_URL = "jdbc:sqlite:./config/sqlite3.db";

    public static Connection getConnection() throws Exception {
        Class.forName("org.sqlite.JDBC");
        File file = new File(DB_URL.substring("jdbc:sqlite:".length())).getAbsoluteFile();
        _LOG.info("database FilePath :{}", file.getAbsolutePath());
        Connection conn = DriverManager.getConnection(DB_URL);
        return conn;
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/util/DbUtil.java
================================================
package com.zzg.mybatis.generator.util;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.zzg.mybatis.generator.exception.DbDriverLoadingException;
import com.zzg.mybatis.generator.model.DatabaseConfig;
import com.zzg.mybatis.generator.model.DbType;
import com.zzg.mybatis.generator.model.UITableColumnVO;
import com.zzg.mybatis.generator.view.AlertUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.mybatis.generator.internal.util.ClassloaderUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by Owen on 6/12/16.
 */
public class DbUtil {

    private static final Logger _LOG = LoggerFactory.getLogger(DbUtil.class);
    private static final int DB_CONNECTION_TIMEOUTS_SECONDS = 1;

    private static Map<DbType, Driver> drivers = new HashMap<>();

	private static ExecutorService executorService = Executors.newSingleThreadExecutor();
	private static volatile boolean portForwaring = false;
	private static Map<Integer, Session> portForwardingSession = new ConcurrentHashMap<>();

    public static Session getSSHSession(DatabaseConfig databaseConfig) {
		if (StringUtils.isBlank(databaseConfig.getSshHost())
				|| StringUtils.isBlank(databaseConfig.getSshPort())
				|| StringUtils.isBlank(databaseConfig.getSshUser())
				|| (StringUtils.isBlank(databaseConfig.getPrivateKey()) && StringUtils.isBlank(databaseConfig.getSshPassword()))
		) {
			return null;
		}

		Session session = null;
		try {
			//Set StrictHostKeyChecking property to no to avoid UnknownHostKey issue
			java.util.Properties config = new java.util.Properties();
			config.put("StrictHostKeyChecking", "no");
			JSch jsch = new JSch();
			Integer sshPort = NumberUtils.createInteger(databaseConfig.getSshPort());
			int port = sshPort == null ? 22 : sshPort;
			session = jsch.getSession(databaseConfig.getSshUser(), databaseConfig.getSshHost(), port);
			if (StringUtils.isNotBlank(databaseConfig.getPrivateKey())) {
				//使用秘钥方式认证
				jsch.addIdentity(databaseConfig.getPrivateKey(), StringUtils.defaultIfBlank(databaseConfig.getPrivateKeyPassword(), null));
			}else {
				session.setPassword(databaseConfig.getSshPassword());
			}
			session.setConfig(config);
		}catch (JSchException e) {
			//Ignore
		}
		return session;
	}

	public static void engagePortForwarding(Session sshSession, DatabaseConfig config) {
		if (sshSession != null) {
			AtomicInteger assinged_port = new AtomicInteger();
			Future<?> result = executorService.submit(() -> {
				try {
					Integer localPort = NumberUtils.createInteger(config.getLport());
					Integer RemotePort = NumberUtils.createInteger(config.getRport());
					int lport = localPort == null ? Integer.parseInt(config.getPort()) : localPort;
					int rport = RemotePort == null ? Integer.parseInt(config.getPort()) : RemotePort;
					Session session = portForwardingSession.get(lport);
					if (session != null && session.isConnected()) {
						String s = session.getPortForwardingL()[0];
						String[] split = StringUtils.split(s, ":");
						boolean portForwarding = String.format("%s:%s", split[0], split[1]).equals(lport + ":" + config.getHost());
						if (portForwarding) {
							return;
						}
					}
					sshSession.connect();
					assinged_port.set(sshSession.setPortForwardingL(lport, config.getHost(), rport));
					portForwardingSession.put(lport, sshSession);
					portForwaring = true;
					_LOG.info("portForwarding Enabled, {}", assinged_port);
				} catch (JSchException e) {
					_LOG.error("Connect Over SSH failed", e);
					if (e.getCause() != null && e.getCause().getMessage().equals("Address already in use: JVM_Bind")) {
						throw new RuntimeException("Address already in use: JVM_Bind");
					}
					throw new RuntimeException(e.getMessage());
				}
			});
			try {
				result.get(5, TimeUnit.SECONDS);
			}catch (Exception e) {
				shutdownPortForwarding(sshSession);
				if (e.getCause() instanceof RuntimeException) {
					throw (RuntimeException)e.getCause();
				}
				if (e instanceof TimeoutException) {
					throw new RuntimeException("OverSSH 连接超时:超过5秒");
				}

				_LOG.info("executorService isShutdown:{}", executorService.isShutdown());
				AlertUtil.showErrorAlert("OverSSH 失败,请检查连接设置:" + e.getMessage());
			}
		}
	}

	public static void shutdownPortForwarding(Session session) {
		portForwaring = false;
		if (session != null && session.isConnected()) {
			session.disconnect();
			_LOG.info("portForwarding turn OFF");
		}
//		executorService.shutdown();
	}

    public static Connection getConnection(DatabaseConfig config) throws ClassNotFoundException, SQLException {
		DbType dbType = DbType.valueOf(config.getDbType());
		if (drivers.get(dbType) == null){
			loadDbDriver(dbType);
		}

		String url = getConnectionUrlWithSchema(config);
	    Properties props = new Properties();

	    props.setProperty("user", config.getUsername()); //$NON-NLS-1$
	    props.setProperty("password", config.getPassword()); //$NON-NLS-1$

		DriverManager.setLoginTimeout(DB_CONNECTION_TIMEOUTS_SECONDS);
	    Connection connection = drivers.get(dbType).connect(url, props);
        _LOG.info("getConnection, connection url: {}", connection);
        return connection;
    }

    public static List<String> getTableNames(DatabaseConfig config, String filter) throws Exception {
		Session sshSession = getSSHSession(config);
		engagePortForwarding(sshSession, config);
		try (Connection connection = getConnection(config)) {
			List<String> tables = new ArrayList<>();
			DatabaseMetaData md = connection.getMetaData();
			ResultSet rs;
			if (DbType.valueOf(config.getDbType()) == DbType.SQL_Server) {
				String sql = "select name from sysobjects  where xtype='u' or xtype='v' order by name";
				rs = connection.createStatement().executeQuery(sql);
				while (rs.next()) {
					tables.add(rs.getString("name"));
				}
			} else if (DbType.valueOf(config.getDbType()) == DbType.Oracle) {
				rs = md.getTables(null, config.getUsername().toUpperCase(), null, new String[]{"TABLE", "VIEW"});
			} else if (DbType.valueOf(config.getDbType()) == DbType.Sqlite) {
				String sql = "Select name from sqlite_master;";
				rs = connection.createStatement().executeQuery(sql);
				while (rs.next()) {
					tables.add(rs.getString("name"));
				}
			} else {
				// rs = md.getTables(null, config.getUsername().toUpperCase(), null, null);
				rs = md.getTables(config.getSchema(), null, "%", new String[]{"TABLE", "VIEW"});//针对 postgresql 的左侧数据表显示
			}
			while (rs.next()) {
				tables.add(rs.getString(3));
			}
			if (StringUtils.isNotBlank(filter)) {
				tables.removeIf(x -> !x.contains(filter) && !(x.replaceAll("_", "").contains(filter)));;
			}
			if (tables.size() > 1) {
				Collections.sort(tables);
			}
			return tables;
		} finally {
			shutdownPortForwarding(sshSession);
		}
	}

    public static List<UITableColumnVO> getTableColumns(DatabaseConfig dbConfig, String tableName) throws Exception {
        String url = getConnectionUrlWithSchema(dbConfig);
        _LOG.info("getTableColumns, connection url: {}", url);
		Session sshSession = getSSHSession(dbConfig);
		engagePortForwarding(sshSession, dbConfig);
		Connection conn = getConnection(dbConfig);
		try {
			DatabaseMetaData md = conn.getMetaData();
			ResultSet rs = md.getColumns(dbConfig.getSchema(), null, tableName, null);
			List<UITableColumnVO> columns = new ArrayList<>();
			while (rs.next()) {
				UITableColumnVO columnVO = new UITableColumnVO();
				String columnName = rs.getString("COLUMN_NAME");
				columnVO.setColumnName(columnName);
				columnVO.setJdbcType(rs.getString("TYPE_NAME"));
				columns.add(columnVO);
			}
			return columns;
		} finally {
			conn.close();
			shutdownPortForwarding(sshSession);
		}
	}

    public static String getConnectionUrlWithSchema(DatabaseConfig dbConfig) throws ClassNotFoundException {
		DbType dbType = DbType.valueOf(dbConfig.getDbType());
		String connectionUrl = String.format(dbType.getConnectionUrlPattern(),
				portForwaring ? "127.0.0.1" : dbConfig.getHost(), portForwaring ? dbConfig.getLport() : dbConfig.getPort(), dbConfig.getSchema(), dbConfig.getEncoding());
        _LOG.info("getConnectionUrlWithSchema, connection url: {}", connectionUrl);
        return connectionUrl;
    }

	/**
	 * 加载数据库驱动
	 * @param dbType 数据库类型
	 */
	private static void loadDbDriver(DbType dbType){
		List<String> driverJars = ConfigHelper.getAllJDBCDriverJarPaths();
		ClassLoader classloader = ClassloaderUtility.getCustomClassloader(driverJars);
		try {
			Class clazz = Class.forName(dbType.getDriverClass(), true, classloader);
			Driver driver = (Driver) clazz.newInstance();
			_LOG.info("load driver class: {}", driver);
			drivers.put(dbType, driver);
		} catch (Exception e) {
			_LOG.error("load driver error", e);
			throw new DbDriverLoadingException("找不到"+dbType.getConnectorJarFile()+"驱动");
		}
	}
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/util/MyStringUtils.java
================================================
package com.zzg.mybatis.generator.util;

/**
 * Created by Owen on 6/18/16.
 */
public class MyStringUtils {

    /**
     *
     * convert string from slash style to camel style, such as my_course will convert to MyCourse
     *
     * @param str
     * @return
     */
    public static String dbStringToCamelStyle(String str) {
        if (str != null) {
            if (str.contains("_")) {
                str = str.toLowerCase();
                StringBuilder sb = new StringBuilder();
                sb.append(String.valueOf(str.charAt(0)).toUpperCase());
                for (int i = 1; i < str.length(); i++) {
                    char c = str.charAt(i);
                    if (c != '_') {
                        sb.append(c);
                    } else {
                        if (i + 1 < str.length()) {
                            sb.append(String.valueOf(str.charAt(i + 1)).toUpperCase());
                            i++;
                        }
                    }
                }
                return sb.toString();
            } else {
                String firstChar = String.valueOf(str.charAt(0)).toUpperCase();
                String otherChars = str.substring(1);
                return firstChar + otherChars;
            }
        }
        return null;
    }

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/view/AlertUtil.java
================================================
package com.zzg.mybatis.generator.view;

import javafx.scene.control.Alert;

/**
 * Created by Owen on 6/21/16.
 */
public class AlertUtil {

    public static void showInfoAlert(String message) {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setContentText(message);
        alert.show();
    }

    public static void showWarnAlert(String message) {
        Alert alert = new Alert(Alert.AlertType.WARNING);
        alert.setContentText(message);
        alert.show();
    }

    public static void showErrorAlert(String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setContentText(message);
        alert.show();
    }

    /**
     * build both OK and Cancel buttons for the user
     * to click on to dismiss the dialog.
     *
     * @param message
     */
    public static Alert buildConfirmationAlert(String message) {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setContentText(message);
        return alert;
    }

}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/view/LeftDbTreeCell.java
================================================
package com.zzg.mybatis.generator.view;

import com.zzg.mybatis.generator.model.DatabaseConfig;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.WeakInvalidationListener;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.layout.HBox;

import java.lang.ref.WeakReference;

/**
 * Created by Owen on 6/14/16.
 */
public class LeftDbTreeCell extends TreeCell<DatabaseConfig> {
    private HBox hbox;

    private WeakReference<TreeItem<DatabaseConfig>> treeItemRef;

    private InvalidationListener treeItemGraphicListener = observable -> {
        updateDisplay(getItem(), isEmpty());
    };

    private InvalidationListener treeItemListener = new InvalidationListener() {
        @Override
        public void invalidated(Observable observable) {
            TreeItem<DatabaseConfig> oldTreeItem = treeItemRef == null ? null : treeItemRef.get();
            if (oldTreeItem != null) {
                oldTreeItem.graphicProperty().removeListener(weakTreeItemGraphicListener);
            }

            TreeItem<DatabaseConfig> newTreeItem = getTreeItem();
            if (newTreeItem != null) {
                newTreeItem.graphicProperty().addListener(weakTreeItemGraphicListener);
                treeItemRef = new WeakReference<TreeItem<DatabaseConfig>>(newTreeItem);
            }
        }
    };

    private WeakInvalidationListener weakTreeItemGraphicListener =
            new WeakInvalidationListener(treeItemGraphicListener);

    private WeakInvalidationListener weakTreeItemListener =
            new WeakInvalidationListener(treeItemListener);

    public LeftDbTreeCell() {
        treeItemProperty().addListener(weakTreeItemListener);

        if (getTreeItem() != null) {
            getTreeItem().graphicProperty().addListener(weakTreeItemGraphicListener);
        }
    }

    void updateDisplay(DatabaseConfig item, boolean empty) {
        if (item == null || empty) {
            hbox = null;
            setText(null);
            setGraphic(null);
        } else {
            // update the graphic if one is set in the TreeItem
            TreeItem<DatabaseConfig> treeItem = getTreeItem();
            if (treeItem != null && treeItem.getGraphic() != null) {
                hbox = null;
                setText(item.toString());
                setGraphic(treeItem.getGraphic());
            } else {
                hbox = null;
                setText(item.getName());
                setGraphic(null);
            }
        }
    }

    @Override
    public void updateItem(DatabaseConfig item, boolean empty) {
        super.updateItem(item, empty);
        updateDisplay(item, empty);
    }
}


================================================
FILE: src/main/java/com/zzg/mybatis/generator/view/UIProgressCallback.java
================================================
package com.zzg.mybatis.generator.view;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.Alert;
import org.mybatis.generator.api.ProgressCallback;

/**
 * Created by Owen on 6/21/16.
 */
public class UIProgressCallback extends Alert implements ProgressCallback  {

    private StringProperty progressText = new SimpleStringProperty();

    public UIProgressCallback(AlertType alertType) {
		super(alertType);
		this.contentTextProperty().bindBidirectional(progressText);
    }

    @Override
    public void introspectionStarted(int totalTasks) {
		progressText.setValue("开始代码检查");
	}

    @Override
    public void generationStarted(int totalTasks) {
		progressText.setValue("开始代码生成");
    }

    @Override
    public void saveStarted(int totalTasks) {
		progressText.setValue("开始保存生成的文件");
    }

    @Override
    public void startTask(String taskName) {
		progressText.setValue("代码生成任务开始");
    }

    @Override
    public void done() {
		progressText.setValue("代码生成完成");
    }

    @Override
    public void checkCancel() throws InterruptedException {
    }
}


================================================
FILE: src/main/resources/fxml/MainUI.fxml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<BorderPane prefHeight="613.0" prefWidth="918.0" stylesheets="@../style.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zzg.mybatis.generator.controller.MainUIController">
    <top>
        <VBox>
            <children>
                <ToolBar minHeight="70.0" prefHeight="81.0" prefWidth="918.0" BorderPane.alignment="CENTER">
                    <items>
                        <Label fx:id="connectionLabel" contentDisplay="TOP" text="数据库连接">
                            <cursor>
                                <Cursor fx:constant="HAND" />
                            </cursor>
                     <font>
                        <Font size="14.0" />
                     </font>
                     <padding>
                        <Insets left="10.0" right="10.0" />
                     </padding>
                        </Label>
                  <Label fx:id="configsLabel" contentDisplay="TOP" text="配置">
                     <padding>
                        <Insets right="10.0" />
                     </padding></Label>
                    </items>
                </ToolBar>
            </children>
        </VBox>
    </top>
    <center>
        <SplitPane dividerPositions="0.15">
            <items>
                <AnchorPane maxWidth="500.0" minWidth="100.0" prefHeight="618.0" prefWidth="200.0">
                    <children>
                        <TreeView fx:id="leftDBTree" layoutX="-14.0" maxWidth="134.0" prefHeight="503.0" prefWidth="134.0" AnchorPane.bottomAnchor="27.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                  <TextField fx:id="filterTreeBox" layoutY="504.0" prefHeight="26.0" prefWidth="134.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.bottomAnchor="0.0" promptText="搜索" />
                    </children>
                </AnchorPane>
            <AnchorPane minWidth="400.0">
               <children>
                  <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                     <children>
                              <GridPane alignment="TOP_RIGHT" layoutX="5.0" layoutY="29.0" prefHeight="505.0" prefWidth="766.0" vgap="5.0" AnchorPane.leftAnchor="-5.0" AnchorPane.rightAnchor="10.0">
                                  <columnConstraints>
                                      <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" maxWidth="157.0" minWidth="132.0" prefWidth="138.0" />
                                      <ColumnConstraints hgrow="SOMETIMES" maxWidth="688.0" minWidth="10.0" prefWidth="222.0" />
                                      <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" maxWidth="688.0" minWidth="69.0" prefWidth="76.0" />
                                      <ColumnConstraints hgrow="SOMETIMES" maxWidth="688.0" minWidth="10.0" prefWidth="108.0" />
                              <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" maxWidth="688.0" minWidth="10.0" prefWidth="129.0" />
                              <ColumnConstraints hgrow="SOMETIMES" maxWidth="688.0" minWidth="10.0" prefWidth="95.0" />
                                  </columnConstraints>
                                  <rowConstraints>
                                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                                      <RowConstraints maxHeight="44.0" minHeight="10.0" prefHeight="27.0" vgrow="SOMETIMES" />
                                      <RowConstraints maxHeight="25.0" minHeight="8.0" prefHeight="25.0" vgrow="SOMETIMES" />
                                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                              <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                              <RowConstraints maxHeight="91.0" minHeight="0.0" prefHeight="0.0" vgrow="SOMETIMES" />
                              <RowConstraints maxHeight="182.0" minHeight="8.0" prefHeight="182.0" vgrow="SOMETIMES" />
                              <RowConstraints maxHeight="99.0" minHeight="11.0" prefHeight="43.0" />
                                  </rowConstraints>
                                  <children>
                                      <Label text="表名" />
                                      <TextField fx:id="tableNameField" disable="true" editable="false" prefHeight="27.0" prefWidth="156.0" promptText="person" GridPane.columnIndex="1">
                                          <GridPane.margin>
                                              <Insets left="5.0" right="5.0" />
                                          </GridPane.margin>
                                      </TextField>
                                      <Label text="Java实体类名" GridPane.rowIndex="1" />
                              <HBox alignment="CENTER_LEFT" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="1" GridPane.valignment="CENTER">
                                 <children>
                                            <TextField fx:id="domainObjectNameField" prefHeight="27.0" prefWidth="154.0" promptText="Person" GridPane.columnIndex="1" GridPane.rowIndex="2">
                                                <GridPane.margin>
                                                    <Insets left="5.0" right="5.0" />
                                                </GridPane.margin>
                                       <HBox.margin>
                                          <Insets right="5.0" />
                                       </HBox.margin>
                                            </TextField>
                                    <Button mnemonicParsing="false" onAction="#openTableColumnCustomizationPage" text="定制列">
                                       <styleClass>
                                          <String fx:value="btn" />
                                          <String fx:value="btn-default" />
                                       </styleClass>
                                    </Button>
                                 </children>
                                 <GridPane.margin>
                                    <Insets left="5.0" />
                                 </GridPane.margin>
                              </HBox>
                              <Label text="主键(选填)" GridPane.rowIndex="2" />
                              <HBox alignment="CENTER_LEFT" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="2" GridPane.valignment="CENTER">
                                 <children>
                                            <TextField fx:id="generateKeysField" prefHeight="25.0" prefWidth="216.0" promptText="primary key, such as id" GridPane.columnIndex="1" GridPane.rowIndex="3">
                                                <GridPane.margin>
                                                    <Insets left="5.0" right="5.0" />
                                                </GridPane.margin>
                                       <HBox.margin>
                                          <Insets right="5.0" />
                                       </HBox.margin>
                                            </TextField>
                                 </children>
                                 <GridPane.margin>
                                    <Insets left="5.0" />
                                 </GridPane.margin>
                              </HBox>
                                      <Label text="项目所在目录" GridPane.rowIndex="3" />
                                      <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.columnSpan="4" GridPane.rowIndex="3">
                                          <children>
                                              <TextField fx:id="projectFolderField" prefHeight="27.0" prefWidth="463.0" promptText="D:\workspace\example">
                                                  <HBox.margin>
                                                      <Insets left="5.0" right="5.0" />
                                                  </HBox.margin>
                                              </TextField>
                                              <Button mnemonicParsing="false" onAction="#chooseProjectFolder" text="选择">
                                       <styleClass>
                                          <String fx:value="btn" />
                                          <String fx:value="btn-default" />
                                       </styleClass></Button>
                                          </children>
                                      </HBox>
                                      <Label text="实体类名包名" GridPane.rowIndex="4" />
                                        <TextField fx:id="modelTargetPackage" prefHeight="27.0" prefWidth="152.0" promptText="com.example.model" GridPane.columnIndex="1" GridPane.rowIndex="4">
                                            <HBox.margin>
                                                <Insets right="5.0" />
                                            </HBox.margin>
                                 <GridPane.margin>
                                    <Insets left="5.0" right="5.0" />
                                 </GridPane.margin>
                                        </TextField>
                                      <Label text="存放目录" GridPane.columnIndex="2" GridPane.rowIndex="4" />
                                      <TextField fx:id="modelTargetProject" prefHeight="27.0" prefWidth="228.0" promptText="src/main/java" text="src/main/java" GridPane.columnIndex="3" GridPane.columnSpan="2" GridPane.rowIndex="4">
                                 <GridPane.margin>
                                    <Insets left="5.0" />
                                 </GridPane.margin></TextField>
                                      <Label text="Mapper接口包名" GridPane.rowIndex="5" />
                                        <TextField fx:id="daoTargetPackage" prefHeight="27.0" prefWidth="248.0" promptText="com.example.mapper" GridPane.columnIndex="1" GridPane.rowIndex="5">
                                            <HBox.margin>
                                                <Insets right="5.0" />
                                            </HBox.margin>
                                 <GridPane.margin>
                                    <Insets left="5.0" right="5.0" />
                                 </GridPane.margin>
                                        </TextField>
                                      <Label text="存放目录" GridPane.columnIndex="2" GridPane.rowIndex="5" />
                                      <TextField fx:id="daoTargetProject" prefHeight="27.0" prefWidth="155.0" promptText="src/main/java" text="src/main/java" GridPane.columnIndex="3" GridPane.columnSpan="2" GridPane.rowIndex="5">
                                 <GridPane.margin>
                                    <Insets left="5.0" />
                                 </GridPane.margin></TextField>
                                      <Label prefHeight="27.0" prefWidth="99.0" text="映射XML文件包名" GridPane.rowIndex="7" />
                                        <TextField fx:id="mapperTargetPackage" prefHeight="27.0" prefWidth="248.0" promptText="com.example" GridPane.columnIndex="1" GridPane.rowIndex="7">
                                            <HBox.margin>
                                                <Insets right="5.0" />
                                            </HBox.margin>
                                 <GridPane.margin>
                                    <Insets left="5.0" right="5.0" />
                                 </GridPane.margin>
                                        </TextField>
                                      <Label text="存放目录" GridPane.columnIndex="2" GridPane.rowIndex="7" />
                                      <TextField fx:id="mappingTargetProject" prefHeight="27.0" prefWidth="155.0" promptText="src/main/resources" text="src/main/resources" GridPane.columnIndex="3" GridPane.columnSpan="2" GridPane.rowIndex="7">
                                 <GridPane.margin>
                                    <Insets left="5.0" />
                                 </GridPane.margin></TextField>
                              <VBox prefHeight="53.0" prefWidth="536.0" spacing="10.0" GridPane.columnIndex="1" GridPane.columnSpan="4" GridPane.rowIndex="9">
                                 <children>
                                    <HBox alignment="CENTER_LEFT">
                                       <children>
                                           <Label text="生成文件的编码" />
                                           <ChoiceBox fx:id="encodingChoice" prefHeight="23.0" prefWidth="71.0">
                                               <items>
                                                   <FXCollections fx:factory="observableArrayList">
                                                       <String fx:value="UTF-8" />
                                                   </FXCollections>
                                               </items>
                                           </ChoiceBox>
                                       </children>
                                    </HBox>
                                    <HBox alignment="CENTER_LEFT" spacing="10.0" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="8">
                                       <children>
                                           <CheckBox fx:id="useExample" minWidth="100.0" mnemonicParsing="false" text="使用Example" />
                                          <CheckBox fx:id="offsetLimitCheckBox" disable="true" minWidth="100.0" mnemonicParsing="false" selected="true" text="分页插件(暂时只支持MySQL和PostgreSQL)" GridPane.columnIndex="1" GridPane.rowIndex="8" />
                                       </children>
                                    </HBox>
                                    <HBox prefHeight="100.0" prefWidth="200.0" spacing="18.0">
                                       <children>
                                          <CheckBox fx:id="commentCheckBox" mnemonicParsing="false" selected="true" text="生成实体域注释(来自表注释)" />
                                          <CheckBox fx:id="overrideXML" mnemonicParsing="false" selected="true" text="覆盖原XML" />
                                       </children>
                                    </HBox>
                                    <HBox spacing="18.0">
                                       <children>
                                          <CheckBox fx:id="useLombokPlugin" mnemonicParsing="false" text="LombokPlugin" />
                                          <CheckBox fx:id="needToStringHashcodeEquals" mnemonicParsing="false" selected="true" text="生成toString/hashCode/equals方法" />
                                          <CheckBox fx:id="useSchemaPrefix" mnemonicParsing="false" text="使用Schema前缀" />
                                       </children>
                                    </HBox>
                                     <HBox prefHeight="100.0" prefWidth="200.0" spacing="18.0">
                                         <children>
                                             <CheckBox fx:id="forUpdateCheckBox" mnemonicParsing="false" selected="false" text="select 增加ForUpdate" />
                                             <CheckBox fx:id="annotationDAOCheckBox" mnemonicParsing="false" selected="true" text="DAO使用 @Repository 注解" />
                                         </children>
                                     </HBox>
                                     <HBox prefHeight="100.0" prefWidth="200.0">
                                         <children>
                                             <CheckBox fx:id="useDAOExtendStyle" mnemonicParsing="false" selected="true" text="DAO方法抽出到公共父接口">
                                             <HBox.margin>
                                                <Insets right="10.0" />
                                             </HBox.margin></CheckBox>
                                             <CheckBox fx:id="jsr310Support" mnemonicParsing="false" prefHeight="16.0" prefWidth="252.0" text="JSR310: Date and Time API" />
                                         </children>
                                     </HBox>
                                    <HBox spacing="18.0">
                                       <children>
                                          <CheckBox fx:id="annotationCheckBox" mnemonicParsing="false" selected="false" text="生成JPA注解" />
                                          <CheckBox fx:id="useActualColumnNamesCheckbox" mnemonicParsing="false" selected="false" text="使用实际的列名" />
                                           <CheckBox fx:id="useTableNameAliasCheckbox" mnemonicParsing="false" selected="false" text="启用as别名查询" />
                                       </children>
                                    </HBox>
                                     <HBox prefHeight="100.0" prefWidth="200.0" />
                                 </children>
                                 <padding>
                                    <Insets left="5.0" />
                                 </padding>
                              </VBox>
                              <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="10">
                                 <children>
                                    <Button mnemonicParsing="false" onAction="#generateCode" text="代码生成">
                                       <styleClass>
                                          <String fx:value="btn-success" />
                                          <String fx:value="btn" />
                                       </styleClass>
                                    </Button>
                                    <Button mnemonicParsing="false" onAction="#saveGeneratorConfig" text="保存配置">
                                       <styleClass>
                                          <String fx:value="btn" />
                                          <String fx:value="btn-default" />
                                       </styleClass>
                                    </Button>
                                     <Button mnemonicParsing="false" onAction="#openTargetFolder" text="打开生成文件夹">
                                         <styleClass>
                                             <String fx:value="btn" />
                                             <String fx:value="btn-default" />
                                         </styleClass>
                                     </Button>
                                 </children>
                              </HBox>
                              <Label text="自定义接口名称(选填)" GridPane.rowIndex="6">
                                 <padding>
                                    <Insets left="5.0" />
                                 </padding>
                              </Label>
                              <TextField fx:id="mapperName" prefHeight="27.0" prefWidth="532.0" promptText="PersonDAO" GridPane.columnIndex="1" GridPane.columnSpan="4" GridPane.rowIndex="6">
                                 <GridPane.margin>
                                    <Insets left="5.0" />
                                 </GridPane.margin>
                              </TextField>
                                  </children>
                              </GridPane>
                     </children>
                     <padding>
                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                     </padding>
                  </VBox>
               </children>
            </AnchorPane>
            </items>
        </SplitPane>
    </center>
</BorderPane>


================================================
FILE: src/main/resources/fxml/basicConnection.fxml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>

<AnchorPane prefHeight="350.0" prefWidth="769.0" stylesheets="@../style.css" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zzg.mybatis.generator.controller.DbConnectionController">

  <GridPane alignment="CENTER_RIGHT" prefHeight="350.0" prefWidth="769.0" AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="20.0">
    <columnConstraints>
      <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" maxWidth="273.0" minWidth="10.0" prefWidth="180.0" />
      <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" maxWidth="273.0" minWidth="10.0" prefWidth="38.0" />
      <ColumnConstraints hgrow="SOMETIMES" maxWidth="482.0" minWidth="10.0" prefWidth="439.0" />
      <ColumnConstraints hgrow="SOMETIMES" maxWidth="482.0" minWidth="10.0" prefWidth="112.0" />
    </columnConstraints>
    <children>
      <Label text="保存名称" />
      <TextField fx:id="nameField" prefHeight="23.0" prefWidth="383.0" GridPane.columnIndex="2" />
      <Label text="数据库类型" GridPane.rowIndex="1" />
      <ChoiceBox fx:id="dbTypeChoice" prefWidth="150.0" GridPane.columnIndex="2" GridPane.rowIndex="1">
        <items>
          <FXCollections fx:factory="observableArrayList">
            <String fx:value="MySQL" />
            <String fx:value="MySQL_8" />
            <String fx:value="Oracle" />
            <String fx:value="PostgreSQL" />
            <String fx:value="SQL_Server" />
            <String fx:value="Sqlite" />
          </FXCollections>
        </items>
      </ChoiceBox>
      <Label text="主机名或IP地址" GridPane.rowIndex="2" />
      <TextField fx:id="hostField" GridPane.columnIndex="2" GridPane.rowIndex="2" />
      <Label text="端口号" GridPane.rowIndex="3" />
      <TextField fx:id="portField" maxWidth="-Infinity" prefHeight="27.0" prefWidth="103.0" GridPane.columnIndex="2" GridPane.rowIndex="3" />
      <Label text="用户名" GridPane.rowIndex="4" />
      <TextField fx:id="userNameField" minWidth="-Infinity" GridPane.columnIndex="2" GridPane.rowIndex="4" />
      <Label text="密码" GridPane.rowIndex="5" />
      <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="2" GridPane.rowIndex="5">
        <children>
          <PasswordField fx:id="passwordField" />
          <CheckBox fx:id="savePwdCheckBox" mnemonicParsing="false" text="Save password" visible="false" />
        </children>
      </HBox>
      <Label text="编码" GridPane.rowIndex="7" />
      <TextField fx:id="schemaField" GridPane.columnIndex="2" GridPane.rowIndex="6" />
      <ChoiceBox fx:id="encodingChoice" maxWidth="1.7976931348623157E308" prefHeight="26.0" prefWidth="404.0" GridPane.columnIndex="2" GridPane.hgrow="ALWAYS" GridPane.rowIndex="7">
        <items>
          <FXCollections fx:factory="observableArrayList">
            <String fx:value="utf8" />
            <String fx:value="gb2312" />
            <String fx:value="gbk" />
          </FXCollections>
        </items>
      </ChoiceBox>
      <Label text="Schema/数据库" GridPane.rowIndex="6" />
    </children>
    <rowConstraints>
      <RowConstraints minHeight="17.0" prefHeight="34.0" />
      <RowConstraints maxHeight="47.0" minHeight="3.0" prefHeight="30.0" />
      <RowConstraints maxHeight="39.0" minHeight="5.0" prefHeight="39.0" />
      <RowConstraints maxHeight="40.0" minHeight="7.0" prefHeight="37.0" />
      <RowConstraints maxHeight="65.0" minHeight="19.0" prefHeight="38.0" />
      <RowConstraints maxHeight="95.0" minHeight="30.0" prefHeight="30.0" />
      <RowConstraints maxHeight="34.0" minHeight="28.0" prefHeight="34.0" />
      <RowConstraints />
    </rowConstraints>
  </GridPane>

</AnchorPane>


================================================
FILE: src/main/resources/fxml/generatorConfigs.fxml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zzg.mybatis.generator.controller.GeneratorConfigController">
   <children>
      <TableView fx:id="configTable" layoutX="47.0" layoutY="53.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <columns>
          <TableColumn fx:id="nameColumn" prefWidth="75.0" text="配置名称" />
          <TableColumn fx:id="opsColumn" editable="false" prefWidth="75.0" sortable="false" text="操作" />
        </columns>
         <columnResizePolicy>
            <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
         </columnResizePolicy>
      </TableView>
   </children>
</AnchorPane>


================================================
FILE: src/main/resources/fxml/newConnection.fxml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import java.lang.String?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane alignment="center" hgap="10" stylesheets="@../style.css" vgap="0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zzg.mybatis.generator.controller.TabPaneController">

  <columnConstraints>
    <ColumnConstraints />
  </columnConstraints>
  <rowConstraints>
    <RowConstraints maxHeight="697.0" minHeight="170.0" />
    <RowConstraints maxHeight="422.0" minHeight="45.0" />
  </rowConstraints>
  <children>
    <TabPane fx:id="tabPane" prefHeight="390.0" prefWidth="769.0" tabClosingPolicy="UNAVAILABLE">
      <tabs>
        <Tab text="TCP/IP">
          <content>
            <fx:include fx:id="tabControlA" source="basicConnection.fxml" />
          </content>
        </Tab>
        <Tab text="SSH">
          <content>
            <fx:include fx:id="tabControlB" source="sshBasedConnection.fxml" />
          </content>
        </Tab>
      </tabs>
    </TabPane>
    <AnchorPane style="-fx-background-color: lightGrey;" GridPane.rowIndex="1">
      <children>
        <Button layoutX="27.0" mnemonicParsing="false" onAction="#testConnection" text="测试连接" AnchorPane.bottomAnchor="15.0" AnchorPane.leftAnchor="15.0" AnchorPane.topAnchor="15.0">
          <styleClass>
            <String fx:value="btn" />
            <String fx:value="btn-default" />
          </styleClass>
        </Button>
        <Button layoutX="615.0" mnemonicParsing="false" onAction="#cancel" style="-fx-border-color: transparent;" text="取消" AnchorPane.bottomAnchor="15.0" AnchorPane.topAnchor="15.0">
          <styleClass>
            <String fx:value="btn" />
            <String fx:value="btn-default" />
          </styleClass>
        </Button>
        <Button layoutX="687.0" mnemonicParsing="false" onAction="#saveConnection" text="保存" textFill="WHITE" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="15.0">
          <styleClass>
            <String fx:value="btn-success" />
            <String fx:value="btn" />
          </styleClass>
        </Button>

      </children>
    </AnchorPane>
  </children>
</GridPane>


================================================
FILE: src/main/resources/fxml/selectTableColumn.fxml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Text?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="526.0" prefWidth="730.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zzg.mybatis.generator.controller.SelectTableColumnController">
   <children>
      <TableView fx:id="columnListView" editable="true" layoutY="123.0" prefHeight="353.0" prefWidth="730.0" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="100.0">
        <columns>
          <TableColumn fx:id="checkedColumn" prefWidth="75.0" text="Checked" />
          <TableColumn fx:id="columnNameColumn" prefWidth="132.0" text="Column Name" />
            <TableColumn fx:id="jdbcTypeColumn" prefWidth="122.0" text="JDBC Type" />
            <TableColumn fx:id="javaTypeColumn" prefWidth="121.0" text="Java Type" />
            <TableColumn fx:id="propertyNameColumn" prefWidth="104.0" text="Property Name" />
            <TableColumn fx:id="typeHandlerColumn" prefWidth="136.0" text="Type Handler" />
        </columns>
         <columnResizePolicy>
            <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
         </columnResizePolicy>
      </TableView>
      <Button focusTraversable="false" layoutX="642.0" layoutY="453.0" mnemonicParsing="false" onAction="#ok" prefHeight="27.0" prefWidth="59.0" text="确认" AnchorPane.bottomAnchor="13.0" AnchorPane.rightAnchor="29.0" />
      <Button focusTraversable="false" layoutX="556.0" layoutY="486.0" mnemonicParsing="false" onAction="#cancel" text="取消" AnchorPane.bottomAnchor="13.0" AnchorPane.rightAnchor="113.0" />
      <Text layoutX="12.0" layoutY="62.0" lineSpacing="5.0" strokeType="OUTSIDE" strokeWidth="0.0" text="2. 如果要定制列的Java数据类型, 编辑Java Type和Property Name或者你自己的Type Handler, 注意要按Enter键保存,然后再点击确认方可生效。" wrappingWidth="706.0" />
      <Text layoutX="14.0" layoutY="35.0" strokeType="OUTSIDE" strokeWidth="0.0" text="1. 如果不想生成某列请取消勾选对应的列" />
      <Button focusTraversable="false" layoutX="14.0" layoutY="489.0" mnemonicParsing="false" onAction="#configAction" text="属性配置" />
   </children>
</AnchorPane>


================================================
FILE: src/main/resources/fxml/sshBasedConnection.fxml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane stylesheets="@../style.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zzg.mybatis.generator.controller.OverSshController">
  <children>
    <GridPane fx:id="gridPane" alignment="CENTER" nodeOrientation="LEFT_TO_RIGHT" AnchorPane.topAnchor="15.0">
      <columnConstraints>
        <ColumnConstraints hgrow="SOMETIMES" maxWidth="340.0" minWidth="19.0" prefWidth="194.0" />
        <ColumnConstraints maxWidth="302.0" minWidth="29.0" prefWidth="36.0" />
        <ColumnConstraints maxWidth="577.0" minWidth="128.0" prefWidth="406.0" />
        <ColumnConstraints maxWidth="446.0" minWidth="113.0" prefWidth="133.0" />
            <ColumnConstraints />
            <ColumnConstraints />
      </columnConstraints>
      <rowConstraints>
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
        <RowConstraints minHeight="35.0" />
            <RowConstraints />
      </rowConstraints>
      <children>
        <Label text="保存名称" GridPane.halignment="RIGHT" GridPane.rowIndex="0" />
        <TextField fx:id="nameField" prefHeight="23.0" prefWidth="373.0" GridPane.columnIndex="2" GridPane.rowIndex="0" />

        <Label text="数据库类型" GridPane.halignment="RIGHT" GridPane.rowIndex="1" />
        <ChoiceBox fx:id="dbTypeChoice" prefWidth="150.0" GridPane.columnIndex="2" GridPane.rowIndex="1">
          <items>
            <FXCollections fx:factory="observableArrayList">
              <String fx:value="MySQL" />
              <String fx:value="MySQL_8" />
              <String fx:value="Oracle" />
              <String fx:value="PostgreSQL" />
              <String fx:value="SQL_Server" />
              <String fx:value="Sqlite" />
            </FXCollections>
          </items>
        </ChoiceBox>
        <Label text="主机名或IP地址" GridPane.halignment="RIGHT" GridPane.rowIndex="2" />
        <TextField fx:id="hostField" prefWidth="376.0" GridPane.columnIndex="2" GridPane.rowIndex="2" />
        <Label text="端口号" GridPane.halignment="RIGHT" GridPane.rowIndex="3" />
        <TextField fx:id="portField" maxWidth="-Infinity" prefHeight="18.0" prefWidth="50.0" GridPane.columnIndex="2" GridPane.rowIndex="3" />
        <Label text="用户名" GridPane.halignment="RIGHT" GridPane.rowIndex="4" />
        <TextField fx:id="userNameField" minWidth="-Infinity" GridPane.columnIndex="2" GridPane.rowIndex="4" />
        <Label text="密码" GridPane.halignment="RIGHT" GridPane.rowIndex="5" />
        <HBox alignment="CENTER_LEFT" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="2" GridPane.rowIndex="5">
          <children>
            <PasswordField fx:id="passwordField" />
            <CheckBox fx:id="savePwdCheckBox" mnemonicParsing="false" text="Save password" visible="false" />
          </children>
        </HBox>

        <Label text="Schema/数据库" GridPane.halignment="RIGHT" GridPane.rowIndex="6" />
        <TextField fx:id="schemaField" GridPane.columnIndex="2" GridPane.rowIndex="6" />

        <Label text="编码" GridPane.halignment="RIGHT" GridPane.rowIndex="7" />
        <ChoiceBox fx:id="encodingChoice" maxWidth="1.7976931348623157E308" prefWidth="150.0" GridPane.columnIndex="2" GridPane.hgrow="ALWAYS" GridPane.rowIndex="7">
          <items>
            <FXCollections fx:factory="observableArrayList">
              <String fx:value="utf8" />
              <String fx:value="gb2312" />
              <String fx:value="gbk" />
            </FXCollections>
          </items>
        </ChoiceBox>

        <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" text="SSH主机名" GridPane.halignment="RIGHT" GridPane.rowIndex="8" />
        <TextField fx:id="sshHostField" maxWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="8" />

        <Label alignment="CENTER_RIGHT" text="SSH端口" textAlignment="RIGHT" GridPane.halignment="RIGHT" GridPane.rowIndex="9" />
        <TextField fx:id="sshdPortField" maxWidth="50.0" minWidth="50.0" prefWidth="50.0" GridPane.columnIndex="2" GridPane.rowIndex="9" />

        <Label text="本机端口" GridPane.halignment="RIGHT" GridPane.rowIndex="10" />
        <TextField fx:id="lportField" maxWidth="50.0" minWidth="50.0" prefWidth="50.0" GridPane.columnIndex="2" GridPane.rowIndex="10" />

        <Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" text="目标端口" textAlignment="RIGHT" GridPane.halignment="RIGHT" GridPane.rowIndex="11" />
        <TextField fx:id="rportField" maxWidth="50.0" minWidth="50.0" prefWidth="50.0" GridPane.columnIndex="2" GridPane.rowIndex="11" />

        <Label text="SSH用户名" GridPane.halignment="RIGHT" GridPane.rowIndex="12" />
        <TextField fx:id="sshUserField" maxWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="12" />

        <Label text="认证方式" GridPane.halignment="RIGHT" GridPane.rowIndex="13" />
        <ChoiceBox fx:id="authTypeChoice" prefWidth="150.0" value="Password" GridPane.columnIndex="2" GridPane.rowIndex
Download .txt
gitextract_tz7ayfc4/

├── .gitignore
├── README.md
├── _config.yml
├── package/
│   └── macosx/
│       └── mybatis-generator-gui.icns
├── pom.xml
└── src/
    ├── main/
    │   ├── java/
    │   │   └── com/
    │   │       └── zzg/
    │   │           └── mybatis/
    │   │               └── generator/
    │   │                   ├── Main.java
    │   │                   ├── MainUI.java
    │   │                   ├── bridge/
    │   │                   │   └── MybatisGeneratorBridge.java
    │   │                   ├── controller/
    │   │                   │   ├── BaseFXController.java
    │   │                   │   ├── DbConnectionController.java
    │   │                   │   ├── FXMLPage.java
    │   │                   │   ├── GeneratorConfigController.java
    │   │                   │   ├── MainUIController.java
    │   │                   │   ├── OverSshController.java
    │   │                   │   ├── PictureProcessStateController.java
    │   │                   │   ├── SelectTableColumnController.java
    │   │                   │   ├── TabPaneController.java
    │   │                   │   └── TableColumnConfigsController.java
    │   │                   ├── exception/
    │   │                   │   └── DbDriverLoadingException.java
    │   │                   ├── model/
    │   │                   │   ├── CachedFXMLLoader.java
    │   │                   │   ├── DatabaseConfig.java
    │   │                   │   ├── DatabaseDTO.java
    │   │                   │   ├── DbType.java
    │   │                   │   ├── GeneratorConfig.java
    │   │                   │   └── UITableColumnVO.java
    │   │                   ├── plugins/
    │   │                   │   ├── CommonDAOInterfacePlugin.java
    │   │                   │   ├── DbRemarksCommentGenerator.java
    │   │                   │   ├── JavaTypeResolverJsr310Impl.java
    │   │                   │   ├── MySQLForUpdatePlugin.java
    │   │                   │   ├── MySQLLimitPlugin.java
    │   │                   │   └── RepositoryPlugin.java
    │   │                   ├── util/
    │   │                   │   ├── ConfigHelper.java
    │   │                   │   ├── ConnectionManager.java
    │   │                   │   ├── DbUtil.java
    │   │                   │   └── MyStringUtils.java
    │   │                   └── view/
    │   │                       ├── AlertUtil.java
    │   │                       ├── LeftDbTreeCell.java
    │   │                       └── UIProgressCallback.java
    │   └── resources/
    │       ├── fxml/
    │       │   ├── MainUI.fxml
    │       │   ├── basicConnection.fxml
    │       │   ├── generatorConfigs.fxml
    │       │   ├── newConnection.fxml
    │       │   ├── selectTableColumn.fxml
    │       │   ├── sshBasedConnection.fxml
    │       │   └── tableColumnConfigs.fxml
    │       ├── lib/
    │       │   ├── mysql-connector-java-5.1.38.jar
    │       │   ├── mysql-connector-java-8.0.11.jar
    │       │   ├── ojdbc6.jar
    │       │   ├── postgresql-9.4.1209.jar
    │       │   ├── sqlite-jdbc-3.19.3.jar
    │       │   └── sqljdbc4-4.0.jar
    │       ├── logback.xml
    │       └── style.css
    └── test/
        └── java/
            └── com/
                └── zzg/
                    └── mybatis/
                        └── generator/
                            └── util/
                                ├── ConfigHelperTest.java
                                └── StringUtilTest.java
Download .txt
SYMBOL INDEX (342 symbols across 35 files)

FILE: src/main/java/com/zzg/mybatis/generator/Main.java
  class Main (line 9) | public class Main {
    method main (line 11) | public static void main(String[] args) {

FILE: src/main/java/com/zzg/mybatis/generator/MainUI.java
  class MainUI (line 21) | public class MainUI extends Application {
    method start (line 25) | @Override
    method main (line 42) | public static void main(String[] args) {

FILE: src/main/java/com/zzg/mybatis/generator/bridge/MybatisGeneratorBridge.java
  class MybatisGeneratorBridge (line 32) | public class MybatisGeneratorBridge {
    method MybatisGeneratorBridge (line 46) | public MybatisGeneratorBridge() {
    method setGeneratorConfig (line 49) | public void setGeneratorConfig(GeneratorConfig generatorConfig) {
    method setDatabaseConfig (line 53) | public void setDatabaseConfig(DatabaseConfig databaseConfig) {
    method generate (line 57) | public void generate() throws Exception {
    method getMappingXMLFilePath (line 273) | private String getMappingXMLFilePath(GeneratorConfig generatorConfig) {
    method setProgressCallback (line 290) | public void setProgressCallback(ProgressCallback progressCallback) {
    method setIgnoredColumns (line 294) | public void setIgnoredColumns(List<IgnoredColumn> ignoredColumns) {
    method setColumnOverrides (line 298) | public void setColumnOverrides(List<ColumnOverride> columnOverrides) {

FILE: src/main/java/com/zzg/mybatis/generator/controller/BaseFXController.java
  class BaseFXController (line 19) | public abstract class BaseFXController implements Initializable {
    method loadFXMLPage (line 27) | public BaseFXController loadFXMLPage(String title, FXMLPage fxmlPage, ...
    method getPrimaryStage (line 60) | public Stage getPrimaryStage() {
    method setPrimaryStage (line 64) | public void setPrimaryStage(Stage primaryStage) {
    method getDialogStage (line 68) | public Stage getDialogStage() {
    method setDialogStage (line 72) | public void setDialogStage(Stage dialogStage) {
    method showDialogStage (line 76) | public void showDialogStage() {
    method closeDialogStage (line 82) | public void closeDialogStage() {

FILE: src/main/java/com/zzg/mybatis/generator/controller/DbConnectionController.java
  class DbConnectionController (line 16) | public class DbConnectionController extends BaseFXController {
    method initialize (line 41) | @Override
    method saveConnection (line 45) | final void saveConnection() {
    method setMainUIController (line 60) | void setMainUIController(MainUIController controller) {
    method setTabPaneController (line 65) | public void setTabPaneController(TabPaneController tabPaneController) {
    method extractConfigForUI (line 69) | public DatabaseConfig extractConfigForUI() {
    method setConfig (line 94) | public void setConfig(DatabaseConfig config) {

FILE: src/main/java/com/zzg/mybatis/generator/controller/FXMLPage.java
  type FXMLPage (line 8) | public enum FXMLPage {
    method FXMLPage (line 18) | FXMLPage(String fxml) {
    method getFxml (line 22) | public String getFxml() {

FILE: src/main/java/com/zzg/mybatis/generator/controller/GeneratorConfigController.java
  class GeneratorConfigController (line 26) | public class GeneratorConfigController extends BaseFXController {
    method initialize (line 41) | @Override
    method refreshTableView (line 90) | public void refreshTableView() {
    method setMainUIController (line 99) | void setMainUIController(MainUIController mainUIController) {

FILE: src/main/java/com/zzg/mybatis/generator/controller/MainUIController.java
  class MainUIController (line 45) | public class MainUIController extends BaseFXController {
    method initialize (line 120) | @Override
    method displayTables (line 219) | private void displayTables(TreeItem<String> treeItem) {
    method setTooltip (line 267) | private void setTooltip() {
    method loadLeftDBTree (line 280) | void loadLeftDBTree() {
    method chooseProjectFolder (line 301) | @FXML
    method generateCode (line 310) | @FXML
    method validateConfig (line 375) | private String validateConfig() {
    method saveGeneratorConfig (line 390) | @FXML
    method getGeneratorConfigFromUI (line 415) | public GeneratorConfig getGeneratorConfigFromUI() {
    method setGeneratorConfigIntoUI (line 446) | public void setGeneratorConfigIntoUI(GeneratorConfig generatorConfig) {
    method openTableColumnCustomizationPage (line 477) | @FXML
    method setIgnoredColumns (line 499) | public void setIgnoredColumns(List<IgnoredColumn> ignoredColumns) {
    method setColumnOverrides (line 503) | public void setColumnOverrides(List<ColumnOverride> columnOverrides) {
    method checkDirs (line 512) | private boolean checkDirs(GeneratorConfig config) {
    method openTargetFolder (line 547) | @FXML

FILE: src/main/java/com/zzg/mybatis/generator/controller/OverSshController.java
  class OverSshController (line 32) | public class OverSshController extends DbConnectionController {
    method initialize (line 72) | @Override
    method setDbConnectionConfig (line 99) | public void setDbConnectionConfig(DatabaseConfig databaseConfig) {
    method checkInput (line 126) | @FXML
    method setLPortLabelText (line 150) | public void setLPortLabelText(String text) {
    method recoverNotice (line 154) | public void recoverNotice() {
    method extractConfigFromUi (line 158) | public DatabaseConfig extractConfigFromUi() {
    method saveConfig (line 190) | public void saveConfig() {
    method testSSH (line 213) | @FXML
    method reset (line 245) | @FXML
    method choosePubKey (line 257) | public void choosePubKey(ActionEvent actionEvent) {

FILE: src/main/java/com/zzg/mybatis/generator/controller/PictureProcessStateController.java
  class PictureProcessStateController (line 26) | public class PictureProcessStateController {
    method setDialogStage (line 36) | public void setDialogStage(Stage stage) {
    method startPlay (line 40) | public void startPlay() {
    method playFailState (line 99) | public void playFailState(String message, boolean showButton) {
    method showCloseButton (line 114) | private void showCloseButton() {
    method playSuccessState (line 122) | public void playSuccessState(String message, boolean showButton) {
    method close (line 134) | public void close() {

FILE: src/main/java/com/zzg/mybatis/generator/controller/SelectTableColumnController.java
  class SelectTableColumnController (line 22) | public class SelectTableColumnController extends BaseFXController {
    method initialize (line 43) | @Override
    method ok (line 73) | @FXML
    method cancel (line 98) | @FXML
    method configAction (line 103) | @FXML
    method setColumnList (line 111) | public void setColumnList(ObservableList<UITableColumnVO> columns) {
    method setMainUIController (line 115) | public void setMainUIController(MainUIController mainUIController) {
    method getTableName (line 119) | public String getTableName() {
    method setTableName (line 123) | public void setTableName(String tableName) {

FILE: src/main/java/com/zzg/mybatis/generator/controller/TabPaneController.java
  class TabPaneController (line 24) | public class TabPaneController extends BaseFXController {
    method initialize (line 40) | @Override
    method setMainUIController (line 51) | public void setMainUIController(MainUIController mainUIController) {
    method setConfig (line 59) | public void setConfig(DatabaseConfig selectedConfig) {
    method extractConfigForUI (line 73) | private DatabaseConfig extractConfigForUI() {
    method saveConnection (line 81) | @FXML
    method testConnection (line 91) | @FXML
    method cancel (line 167) | @FXML

FILE: src/main/java/com/zzg/mybatis/generator/controller/TableColumnConfigsController.java
  class TableColumnConfigsController (line 27) | public class TableColumnConfigsController extends BaseFXController {
    method initialize (line 41) | @Override
    method cancel (line 46) | @FXML
    method confirm (line 51) | @FXML
    method setColumnListView (line 65) | public void setColumnListView(TableView<UITableColumnVO> columnListVie...
    method setTableName (line 69) | public void setTableName(String tableName) {
    method genProertyNameByColumnNamePrefix (line 74) | private void genProertyNameByColumnNamePrefix() {

FILE: src/main/java/com/zzg/mybatis/generator/exception/DbDriverLoadingException.java
  class DbDriverLoadingException (line 8) | public class DbDriverLoadingException extends RuntimeException{
    method DbDriverLoadingException (line 10) | public DbDriverLoadingException(String message){

FILE: src/main/java/com/zzg/mybatis/generator/model/CachedFXMLLoader.java
  class CachedFXMLLoader (line 3) | public class CachedFXMLLoader {

FILE: src/main/java/com/zzg/mybatis/generator/model/DatabaseConfig.java
  class DatabaseConfig (line 8) | public class DatabaseConfig {
    method getId (line 49) | public Integer getId() {
    method setId (line 53) | public void setId(Integer id) {
    method getName (line 57) | public String getName() {
    method setName (line 61) | public void setName(String name) {
    method getHost (line 65) | public String getHost() {
    method setHost (line 69) | public void setHost(String host) {
    method getPort (line 73) | public String getPort() {
    method setPort (line 77) | public void setPort(String port) {
    method getSchema (line 81) | public String getSchema() {
    method setSchema (line 85) | public void setSchema(String schema) {
    method getUsername (line 89) | public String getUsername() {
    method setUsername (line 93) | public void setUsername(String username) {
    method getPassword (line 97) | public String getPassword() {
    method setPassword (line 101) | public void setPassword(String password) {
    method getEncoding (line 105) | public String getEncoding() {
    method setEncoding (line 109) | public void setEncoding(String encoding) {
    method getDbType (line 113) | public String getDbType() {
    method setDbType (line 117) | public void setDbType(String dbType) {
    method getLport (line 121) | public String getLport() {
    method setLport (line 125) | public void setLport(String lport) {
    method getRport (line 129) | public String getRport() {
    method setRport (line 133) | public void setRport(String rport) {
    method getSshPort (line 137) | public String getSshPort() {
    method setSshPort (line 141) | public void setSshPort(String sshPort) {
    method getSshHost (line 145) | public String getSshHost() {
    method setSshHost (line 149) | public void setSshHost(String sshHost) {
    method getSshUser (line 153) | public String getSshUser() {
    method setSshUser (line 157) | public void setSshUser(String sshUser) {
    method getSshPassword (line 161) | public String getSshPassword() {
    method setSshPassword (line 165) | public void setSshPassword(String sshPassword) {
    method getPrivateKeyPassword (line 169) | public String getPrivateKeyPassword() {
    method setPrivateKeyPassword (line 173) | public void setPrivateKeyPassword(String privateKeyPassword) {
    method getPrivateKey (line 177) | public String getPrivateKey() {
    method setPrivateKey (line 181) | public void setPrivateKey(String privateKey) {
    method equals (line 185) | @Override
    method hashCode (line 209) | @Override
    method toString (line 214) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/model/DatabaseDTO.java
  class DatabaseDTO (line 3) | public class DatabaseDTO {
    method getName (line 9) | public String getName() {
    method setName (line 13) | public void setName(String name) {
    method getValue (line 17) | public int getValue() {
    method setValue (line 21) | public void setValue(int value) {
    method getDriverClass (line 25) | public String getDriverClass() {
    method setDriverClass (line 29) | public void setDriverClass(String driverClass) {
    method toString (line 33) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/model/DbType.java
  type DbType (line 6) | public enum DbType {
    method DbType (line 19) | DbType(String driverClass, String connectionUrlPattern, String connect...
    method getDriverClass (line 25) | public String getDriverClass() {
    method getConnectionUrlPattern (line 29) | public String getConnectionUrlPattern() {
    method getConnectorJarFile (line 33) | public String getConnectorJarFile() {

FILE: src/main/java/com/zzg/mybatis/generator/model/GeneratorConfig.java
  class GeneratorConfig (line 10) | public class GeneratorConfig {
    method isJsr310Support (line 71) | public boolean isJsr310Support() {
    method setJsr310Support (line 75) | public void setJsr310Support(boolean jsr310Support) {
    method isUseSchemaPrefix (line 79) | public boolean isUseSchemaPrefix() {
    method setUseSchemaPrefix (line 83) | public void setUseSchemaPrefix(boolean useSchemaPrefix) {
    method isUseExample (line 87) | public boolean isUseExample() {
    method setUseExample (line 91) | public void setUseExample(boolean useExample) {
    method getName (line 95) | public String getName() {
    method setName (line 99) | public void setName(String name) {
    method getTableName (line 103) | public String getTableName() {
    method setTableName (line 107) | public void setTableName(String tableName) {
    method getDomainObjectName (line 111) | public String getDomainObjectName() {
    method setDomainObjectName (line 115) | public void setDomainObjectName(String domainObjectName) {
    method getConnectorJarPath (line 119) | public String getConnectorJarPath() {
    method setConnectorJarPath (line 123) | public void setConnectorJarPath(String connectorJarPath) {
    method getProjectFolder (line 127) | public String getProjectFolder() {
    method setProjectFolder (line 131) | public void setProjectFolder(String projectFolder) {
    method getModelPackage (line 135) | public String getModelPackage() {
    method setModelPackage (line 139) | public void setModelPackage(String modelPackage) {
    method getModelPackageTargetFolder (line 143) | public String getModelPackageTargetFolder() {
    method setModelPackageTargetFolder (line 147) | public void setModelPackageTargetFolder(String modelPackageTargetFolde...
    method getDaoPackage (line 151) | public String getDaoPackage() {
    method setDaoPackage (line 155) | public void setDaoPackage(String daoPackage) {
    method getDaoTargetFolder (line 159) | public String getDaoTargetFolder() {
    method setDaoTargetFolder (line 163) | public void setDaoTargetFolder(String daoTargetFolder) {
    method getMappingXMLPackage (line 167) | public String getMappingXMLPackage() {
    method setMappingXMLPackage (line 171) | public void setMappingXMLPackage(String mappingXMLPackage) {
    method getMappingXMLTargetFolder (line 175) | public String getMappingXMLTargetFolder() {
    method setMappingXMLTargetFolder (line 179) | public void setMappingXMLTargetFolder(String mappingXMLTargetFolder) {
    method isOffsetLimit (line 183) | public boolean isOffsetLimit() {
    method setOffsetLimit (line 187) | public void setOffsetLimit(boolean offsetLimit) {
    method isComment (line 191) | public boolean isComment() {
    method setComment (line 195) | public void setComment(boolean comment) {
    method isNeedToStringHashcodeEquals (line 199) | public boolean isNeedToStringHashcodeEquals() {
    method setNeedToStringHashcodeEquals (line 203) | public void setNeedToStringHashcodeEquals(boolean needToStringHashcode...
    method isUseLombokPlugin (line 207) | public boolean isUseLombokPlugin() {
    method setUseLombokPlugin (line 211) | public void setUseLombokPlugin(boolean useLombokPlugin) {
    method isNeedForUpdate (line 215) | public boolean isNeedForUpdate() {
    method setNeedForUpdate (line 219) | public void setNeedForUpdate(boolean needForUpdate) {
    method isAnnotationDAO (line 223) | public boolean isAnnotationDAO() {
    method setAnnotationDAO (line 227) | public void setAnnotationDAO(boolean annotationDAO) {
    method isAnnotation (line 231) | public boolean isAnnotation() {
    method setAnnotation (line 235) | public void setAnnotation(boolean annotation) {
    method isUseActualColumnNames (line 239) | public boolean isUseActualColumnNames() {
    method setUseActualColumnNames (line 243) | public void setUseActualColumnNames(boolean useActualColumnNames) {
    method getMapperName (line 247) | public String getMapperName() {
    method setMapperName (line 251) | public void setMapperName(String mapperName) {
    method getGenerateKeys (line 255) | public String getGenerateKeys() {
    method setGenerateKeys (line 259) | public void setGenerateKeys(String generateKeys) {
    method getEncoding (line 263) | public String getEncoding() {
    method setEncoding (line 267) | public void setEncoding(String encoding) {
    method getUseTableNameAlias (line 271) | public boolean getUseTableNameAlias() {
    method setUseTableNameAlias (line 275) | public void setUseTableNameAlias(boolean useTableNameAlias) {
    method isUseTableNameAlias (line 279) | public boolean isUseTableNameAlias() {
    method isOverrideXML (line 283) | public boolean isOverrideXML() {
    method setOverrideXML (line 287) | public void setOverrideXML(boolean overrideXML) {
    method setUseDAOExtendStyle (line 291) | public void setUseDAOExtendStyle(boolean useDAOExtendStyle) {
    method isUseDAOExtendStyle (line 295) | public boolean isUseDAOExtendStyle() {

FILE: src/main/java/com/zzg/mybatis/generator/model/UITableColumnVO.java
  class UITableColumnVO (line 11) | public class UITableColumnVO {
    method getColumnName (line 25) | public String getColumnName() {
    method setColumnName (line 29) | public void setColumnName(String columnName) {
    method getJdbcType (line 33) | public String getJdbcType() {
    method setJdbcType (line 37) | public void setJdbcType(String jdbcType) {
    method getPropertyName (line 41) | public String getPropertyName() {
    method setPropertyName (line 45) | public void setPropertyName(String propertyName) {
    method checkedProperty (line 49) | public BooleanProperty checkedProperty() {
    method getChecked (line 53) | public Boolean getChecked() {
    method setChecked (line 57) | public void setChecked(Boolean checked) {
    method typeHandleProperty (line 61) | public StringProperty typeHandleProperty() {
    method getTypeHandle (line 65) | public String getTypeHandle() {
    method setTypeHandle (line 69) | public void setTypeHandle(String typeHandle) {
    method columnNameProperty (line 73) | public StringProperty columnNameProperty() {
    method jdbcTypeProperty (line 77) | public StringProperty jdbcTypeProperty() {
    method propertyNameProperty (line 81) | public StringProperty propertyNameProperty() {
    method getJavaType (line 85) | public String getJavaType() {
    method javaTypeProperty (line 89) | public StringProperty javaTypeProperty() {
    method setJavaType (line 93) | public void setJavaType(String javaType) {

FILE: src/main/java/com/zzg/mybatis/generator/plugins/CommonDAOInterfacePlugin.java
  class CommonDAOInterfacePlugin (line 19) | public class CommonDAOInterfacePlugin extends PluginAdapter {
    method CommonDAOInterfacePlugin (line 28) | public CommonDAOInterfacePlugin() {
    method isUseExample (line 32) | private boolean isUseExample() {
    method contextGenerateAdditionalJavaFiles (line 36) | @Override
    method clientGenerated (line 95) | @Override
    method validate (line 135) | @Override
    method interceptExampleParam (line 140) | private void interceptExampleParam(Method method) {
    method interceptPrimaryKeyParam (line 148) | private void interceptPrimaryKeyParam(Method method) {
    method interceptModelParam (line 154) | private void interceptModelParam(Method method) {
    method interceptModelAndExampleParam (line 160) | private void interceptModelAndExampleParam(Method method) {
    method clientCountByExampleMethodGenerated (line 179) | @Override
    method clientDeleteByExampleMethodGenerated (line 190) | @Override
    method clientDeleteByPrimaryKeyMethodGenerated (line 200) | @Override
    method clientInsertMethodGenerated (line 207) | @Override
    method clientSelectByExampleWithBLOBsMethodGenerated (line 214) | @Override
    method clientSelectByExampleWithoutBLOBsMethodGenerated (line 224) | @Override
    method clientSelectByPrimaryKeyMethodGenerated (line 234) | @Override
    method clientUpdateByExampleSelectiveMethodGenerated (line 242) | @Override
    method clientUpdateByExampleWithBLOBsMethodGenerated (line 251) | @Override
    method clientUpdateByExampleWithoutBLOBsMethodGenerated (line 260) | @Override
    method clientUpdateByPrimaryKeySelectiveMethodGenerated (line 269) | @Override
    method clientUpdateByExampleWithoutBLOBsMethodGenerated (line 276) | @Override
    method clientUpdateByExampleSelectiveMethodGenerated (line 284) | @Override
    method clientUpdateByPrimaryKeyWithBLOBsMethodGenerated (line 292) | @Override
    method clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated (line 299) | @Override
    method clientInsertSelectiveMethodGenerated (line 307) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/plugins/DbRemarksCommentGenerator.java
  class DbRemarksCommentGenerator (line 37) | public class DbRemarksCommentGenerator implements CommentGenerator {
    method DbRemarksCommentGenerator (line 44) | public DbRemarksCommentGenerator() {
    method addJavaFileComment (line 50) | public void addJavaFileComment(CompilationUnit compilationUnit) {
    method addComment (line 65) | public void addComment(XmlElement xmlElement) {
    method addRootComment (line 68) | public void addRootComment(XmlElement rootElement) {
    method addGeneralMethodAnnotation (line 73) | @Override
    method addGeneralMethodAnnotation (line 79) | @Override
    method addFieldAnnotation (line 84) | @Override
    method addFieldAnnotation (line 89) | @Override
    method addClassAnnotation (line 94) | @Override
    method addConfigurationProperties (line 98) | public void addConfigurationProperties(Properties properties) {
    method addClassComment (line 106) | public void addClassComment(InnerClass innerClass,
    method addModelClassComment (line 110) | public void addModelClassComment(TopLevelClass topLevelClass,
    method addEnumComment (line 121) | public void addEnumComment(InnerEnum innerEnum,
    method addFieldComment (line 125) | public void addFieldComment(Field field,
    method addFieldComment (line 162) | public void addFieldComment(Field field, IntrospectedTable introspecte...
    method addGeneralMethodComment (line 165) | public void addGeneralMethodComment(Method method,
    method addGetterComment (line 169) | public void addGetterComment(Method method,
    method addSetterComment (line 174) | public void addSetterComment(Method method,
    method addClassComment (line 179) | public void addClassComment(InnerClass innerClass,

FILE: src/main/java/com/zzg/mybatis/generator/plugins/JavaTypeResolverJsr310Impl.java
  class JavaTypeResolverJsr310Impl (line 16) | public class JavaTypeResolverJsr310Impl extends JavaTypeResolverDefaultI...
    method overrideDefaultType (line 18) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/plugins/MySQLForUpdatePlugin.java
  class MySQLForUpdatePlugin (line 17) | public class MySQLForUpdatePlugin extends PluginAdapter {
    method validate (line 19) | @Override
    method modelExampleClassGenerated (line 24) | @Override
    method appendForUpdate (line 51) | private void appendForUpdate(XmlElement element, IntrospectedTable int...
    method sqlMapSelectByExampleWithoutBLOBsElementGenerated (line 59) | @Override
    method sqlMapSelectByExampleWithBLOBsElementGenerated (line 65) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/plugins/MySQLLimitPlugin.java
  class MySQLLimitPlugin (line 16) | public class MySQLLimitPlugin extends PluginAdapter {
    method validate (line 18) | @Override
    method modelExampleClassGenerated (line 26) | @Override
    method sqlMapSelectByExampleWithoutBLOBsElementGenerated (line 78) | @Override
    method sqlMapSelectByExampleWithBLOBsElementGenerated (line 103) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/plugins/RepositoryPlugin.java
  class RepositoryPlugin (line 14) | public class RepositoryPlugin extends PluginAdapter {
    method RepositoryPlugin (line 19) | public RepositoryPlugin () {
    method validate (line 23) | @Override
    method clientGenerated (line 28) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/util/ConfigHelper.java
  class ConfigHelper (line 28) | public class ConfigHelper {
    method createEmptyFiles (line 34) | public static void createEmptyFiles() throws Exception {
    method createEmptyXMLFile (line 45) | static void createEmptyXMLFile(File uiConfigFile) throws IOException {
    method loadDatabaseConfig (line 63) | public static List<DatabaseConfig> loadDatabaseConfig() throws Excepti...
    method saveDatabaseConfig (line 88) | public static void saveDatabaseConfig(boolean isUpdate, Integer primar...
    method deleteDatabaseConfig (line 117) | public static void deleteDatabaseConfig(DatabaseConfig databaseConfig)...
    method saveGeneratorConfig (line 133) | public static void saveGeneratorConfig(GeneratorConfig generatorConfig...
    method loadGeneratorConfig (line 151) | public static GeneratorConfig loadGeneratorConfig(String name) throws ...
    method loadGeneratorConfigs (line 174) | public static List<GeneratorConfig> loadGeneratorConfigs() throws Exce...
    method deleteGeneratorConfig (line 197) | public static int deleteGeneratorConfig(String name) throws Exception {
    method findConnectorLibPath (line 212) | public static String findConnectorLibPath(String dbType) {
    method getAllJDBCDriverJarPaths (line 228) | public static List<String> getAllJDBCDriverJarPaths() {

FILE: src/main/java/com/zzg/mybatis/generator/util/ConnectionManager.java
  class ConnectionManager (line 13) | public class ConnectionManager {
    method getConnection (line 17) | public static Connection getConnection() throws Exception {

FILE: src/main/java/com/zzg/mybatis/generator/util/DbUtil.java
  class DbUtil (line 26) | public class DbUtil {
    method getSSHSession (line 37) | public static Session getSSHSession(DatabaseConfig databaseConfig) {
    method engagePortForwarding (line 68) | public static void engagePortForwarding(Session sshSession, DatabaseCo...
    method shutdownPortForwarding (line 116) | public static void shutdownPortForwarding(Session session) {
    method getConnection (line 125) | public static Connection getConnection(DatabaseConfig config) throws C...
    method getTableNames (line 143) | public static List<String> getTableNames(DatabaseConfig config, String...
    method getTableColumns (line 183) | public static List<UITableColumnVO> getTableColumns(DatabaseConfig dbC...
    method getConnectionUrlWithSchema (line 207) | public static String getConnectionUrlWithSchema(DatabaseConfig dbConfi...
    method loadDbDriver (line 219) | private static void loadDbDriver(DbType dbType){

FILE: src/main/java/com/zzg/mybatis/generator/util/MyStringUtils.java
  class MyStringUtils (line 6) | public class MyStringUtils {
    method dbStringToCamelStyle (line 15) | public static String dbStringToCamelStyle(String str) {

FILE: src/main/java/com/zzg/mybatis/generator/view/AlertUtil.java
  class AlertUtil (line 8) | public class AlertUtil {
    method showInfoAlert (line 10) | public static void showInfoAlert(String message) {
    method showWarnAlert (line 16) | public static void showWarnAlert(String message) {
    method showErrorAlert (line 22) | public static void showErrorAlert(String message) {
    method buildConfirmationAlert (line 34) | public static Alert buildConfirmationAlert(String message) {

FILE: src/main/java/com/zzg/mybatis/generator/view/LeftDbTreeCell.java
  class LeftDbTreeCell (line 16) | public class LeftDbTreeCell extends TreeCell<DatabaseConfig> {
    method invalidated (line 26) | @Override
    method LeftDbTreeCell (line 47) | public LeftDbTreeCell() {
    method updateDisplay (line 55) | void updateDisplay(DatabaseConfig item, boolean empty) {
    method updateItem (line 75) | @Override

FILE: src/main/java/com/zzg/mybatis/generator/view/UIProgressCallback.java
  class UIProgressCallback (line 11) | public class UIProgressCallback extends Alert implements ProgressCallbac...
    method UIProgressCallback (line 15) | public UIProgressCallback(AlertType alertType) {
    method introspectionStarted (line 20) | @Override
    method generationStarted (line 25) | @Override
    method saveStarted (line 30) | @Override
    method startTask (line 35) | @Override
    method done (line 40) | @Override
    method checkCancel (line 45) | @Override

FILE: src/test/java/com/zzg/mybatis/generator/util/ConfigHelperTest.java
  class ConfigHelperTest (line 11) | public class ConfigHelperTest {
    method testFindConnectorLibPath_Oracle (line 13) | @Test
    method testFindConnectorLibPath_Mysql (line 19) | @Test
    method testFindConnectorLibPath_PostgreSQL (line 25) | @Test
    method testGetAllJDBCDriverJarPaths (line 31) | @Test

FILE: src/test/java/com/zzg/mybatis/generator/util/StringUtilTest.java
  class StringUtilTest (line 9) | public class StringUtilTest {
    method testDbStringToCamelStyle (line 11) | @Test
    method testDbStringToCamelStyle_case2 (line 17) | @Test
    method testDbStringToCamelStyle_case3 (line 23) | @Test
    method testDbStringToCamelStyle_case4 (line 29) | @Test
    method testDbStringToCamelStyle_case5 (line 35) | @Test
Condensed preview — 55 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (219K chars).
[
  {
    "path": ".gitignore",
    "chars": 105,
    "preview": "/target/\n/config/\n.idea\n.settings\nlogs\n*.iml\n.project\n.classpath\n/src/main/resources/sqlite3.db\n/config/\n"
  },
  {
    "path": "README.md",
    "chars": 2737,
    "preview": "mybatis-generator-gui\n==============\n\nmybatis-generator-gui是基于 [mybatis generator](http://www.mybatis.org/generator/inde"
  },
  {
    "path": "_config.yml",
    "chars": 26,
    "preview": "theme: jekyll-theme-cayman"
  },
  {
    "path": "pom.xml",
    "chars": 4837,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:sc"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/Main.java",
    "chars": 264,
    "preview": "package com.zzg.mybatis.generator;\n\nimport javafx.application.Application;\n\n/**\n * @author 欧闻\n * @version $Id: Main, v 0"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/MainUI.java",
    "chars": 1328,
    "preview": "package com.zzg.mybatis.generator;\n\nimport com.zzg.mybatis.generator.controller.MainUIController;\nimport com.zzg.mybatis"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/bridge/MybatisGeneratorBridge.java",
    "chars": 14823,
    "preview": "package com.zzg.mybatis.generator.bridge;\n\nimport com.jcraft.jsch.Session;\nimport com.zzg.mybatis.generator.controller.P"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/BaseFXController.java",
    "chars": 2981,
    "preview": "package com.zzg.mybatis.generator.controller;\r\n\r\nimport com.zzg.mybatis.generator.view.AlertUtil;\r\nimport javafx.fxml.FX"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/DbConnectionController.java",
    "chars": 3596,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport com.zzg.mybatis.generator.model.DatabaseConfig;\nimport com.zzg.myb"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/FXMLPage.java",
    "chars": 517,
    "preview": "package com.zzg.mybatis.generator.controller;\n\n/**\n * FXML User Interface enum\n * <p>\n * Created by Owen on 6/20/16.\n */"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/GeneratorConfigController.java",
    "chars": 3789,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport com.zzg.mybatis.generator.model.GeneratorConfig;\nimport com.zzg.my"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/MainUIController.java",
    "chars": 23520,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport com.jcraft.jsch.Session;\nimport com.zzg.mybatis.generator.bridge.M"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/OverSshController.java",
    "chars": 9513,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport com.jcraft.jsch.JSchException;\nimport com.jcraft.jsch.Session;\nimp"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/PictureProcessStateController.java",
    "chars": 4874,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport javafx.animation.RotateTransition;\nimport javafx.animation.Timelin"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/SelectTableColumnController.java",
    "chars": 5367,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport com.zzg.mybatis.generator.model.UITableColumnVO;\nimport javafx.col"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/TabPaneController.java",
    "chars": 6261,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport com.jcraft.jsch.Session;\nimport com.zzg.mybatis.generator.model.Da"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/controller/TableColumnConfigsController.java",
    "chars": 3569,
    "preview": "package com.zzg.mybatis.generator.controller;\n\nimport com.zzg.mybatis.generator.model.UITableColumnVO;\nimport com.zzg.my"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/exception/DbDriverLoadingException.java",
    "chars": 256,
    "preview": "package com.zzg.mybatis.generator.exception;\n\n/**\n * 数据库驱动加载异常\n * @Date 2017/8/15 21:46\n * @Author jy\n */\npublic class D"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/model/CachedFXMLLoader.java",
    "chars": 77,
    "preview": "package com.zzg.mybatis.generator.model;\n\npublic class CachedFXMLLoader {\n\n}\n"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/model/DatabaseConfig.java",
    "chars": 4659,
    "preview": "package com.zzg.mybatis.generator.model;\n\nimport java.util.Objects;\n\n/**\n * Created by Owen on 5/13/16.\n */\npublic class"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/model/DatabaseDTO.java",
    "chars": 562,
    "preview": "package com.zzg.mybatis.generator.model;\n\npublic class DatabaseDTO {\n\n\tprivate String name;\n\tprivate int value;\n\tprivate"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/model/DbType.java",
    "chars": 1414,
    "preview": "package com.zzg.mybatis.generator.model;\n\n/**\n * Created by Owen on 6/14/16.\n */\npublic enum DbType {\n\n    MySQL(\"com.my"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/model/GeneratorConfig.java",
    "chars": 5962,
    "preview": "package com.zzg.mybatis.generator.model;\n\n/**\n *\n * GeneratorConfig is the Config of mybatis generator config exclude da"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/model/UITableColumnVO.java",
    "chars": 2263,
    "preview": "package com.zzg.mybatis.generator.model;\n\nimport javafx.beans.property.BooleanProperty;\nimport javafx.beans.property.Sim"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/plugins/CommonDAOInterfacePlugin.java",
    "chars": 12373,
    "preview": "package com.zzg.mybatis.generator.plugins;\n\nimport org.mybatis.generator.api.*;\nimport org.mybatis.generator.api.dom.jav"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/plugins/DbRemarksCommentGenerator.java",
    "chars": 6764,
    "preview": "/*\n *  Copyright 2008 The Apache Software Foundation\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/plugins/JavaTypeResolverJsr310Impl.java",
    "chars": 1528,
    "preview": "package com.zzg.mybatis.generator.plugins;\r\n\r\nimport org.mybatis.generator.api.IntrospectedColumn;\r\nimport org.mybatis.g"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/plugins/MySQLForUpdatePlugin.java",
    "chars": 2579,
    "preview": "package com.zzg.mybatis.generator.plugins;\n\nimport org.mybatis.generator.api.IntrospectedTable;\nimport org.mybatis.gener"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/plugins/MySQLLimitPlugin.java",
    "chars": 4687,
    "preview": "package com.zzg.mybatis.generator.plugins;\n\n/**\n * Created by zouzhigang on 2016/6/14.\n */\n\nimport org.mybatis.generator"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/plugins/RepositoryPlugin.java",
    "chars": 971,
    "preview": "package com.zzg.mybatis.generator.plugins;\n\nimport org.mybatis.generator.api.IntrospectedTable;\nimport org.mybatis.gener"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/util/ConfigHelper.java",
    "chars": 7825,
    "preview": "package com.zzg.mybatis.generator.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.zzg.mybatis.generator.model.Databa"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/util/ConnectionManager.java",
    "chars": 775,
    "preview": "package com.zzg.mybatis.generator.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\n"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/util/DbUtil.java",
    "chars": 9116,
    "preview": "package com.zzg.mybatis.generator.util;\n\nimport com.jcraft.jsch.JSch;\nimport com.jcraft.jsch.JSchException;\nimport com.j"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/util/MyStringUtils.java",
    "chars": 1301,
    "preview": "package com.zzg.mybatis.generator.util;\n\n/**\n * Created by Owen on 6/18/16.\n */\npublic class MyStringUtils {\n\n    /**\n  "
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/view/AlertUtil.java",
    "chars": 1026,
    "preview": "package com.zzg.mybatis.generator.view;\n\nimport javafx.scene.control.Alert;\n\n/**\n * Created by Owen on 6/21/16.\n */\npubl"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/view/LeftDbTreeCell.java",
    "chars": 2718,
    "preview": "package com.zzg.mybatis.generator.view;\n\nimport com.zzg.mybatis.generator.model.DatabaseConfig;\nimport javafx.beans.Inva"
  },
  {
    "path": "src/main/java/com/zzg/mybatis/generator/view/UIProgressCallback.java",
    "chars": 1141,
    "preview": "package com.zzg.mybatis.generator.view;\n\nimport javafx.beans.property.SimpleStringProperty;\nimport javafx.beans.property"
  },
  {
    "path": "src/main/resources/fxml/MainUI.fxml",
    "chars": 20728,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.lang.*?>\n<?import javafx.collections.*?>\n<?import javafx.geometry."
  },
  {
    "path": "src/main/resources/fxml/basicConnection.fxml",
    "chars": 4266,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.lang.String?>\n<?import javafx.collections.FXCollections?>\n<?import"
  },
  {
    "path": "src/main/resources/fxml/generatorConfigs.fxml",
    "chars": 1069,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.control.TableColumn?>\n<?import javafx.scene.control.TableV"
  },
  {
    "path": "src/main/resources/fxml/newConnection.fxml",
    "chars": 2519,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.lang.*?>\n<?import javafx.scene.control.*?>\n<?import javafx.scene.l"
  },
  {
    "path": "src/main/resources/fxml/selectTableColumn.fxml",
    "chars": 2386,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import javafx.scene.control.Button?>\n<?import javafx.scene.control.TableColumn"
  },
  {
    "path": "src/main/resources/fxml/sshBasedConnection.fxml",
    "chars": 9245,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.lang.*?>\n<?import javafx.collections.*?>\n<?import javafx.geometry."
  },
  {
    "path": "src/main/resources/fxml/tableColumnConfigs.fxml",
    "chars": 3748,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<?import java.lang.String?>\n<?import javafx.geometry.Insets?>\n<?import javafx.sc"
  },
  {
    "path": "src/main/resources/logback.xml",
    "chars": 1239,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\t<jmxConfigurator />\n\t<appender name=\"CONSOLE\" class=\"ch.qos.logb"
  },
  {
    "path": "src/main/resources/style.css",
    "chars": 878,
    "preview": "* {\n\t-fx-font-size: 12px;\n}\n\n.button {\n\t-fx-font-size: 14px;\n}\n\n.tool-bar .button {\n    -fx-border-width: 0px;\n}\n\n.btn {"
  },
  {
    "path": "src/test/java/com/zzg/mybatis/generator/util/ConfigHelperTest.java",
    "chars": 987,
    "preview": "package com.zzg.mybatis.generator.util;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.util.List;\n\n/**\n *"
  },
  {
    "path": "src/test/java/com/zzg/mybatis/generator/util/StringUtilTest.java",
    "chars": 1134,
    "preview": "package com.zzg.mybatis.generator.util;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\n/**\n * Created by Owen on 6/18"
  }
]

// ... and 7 more files (download for full content)

About this extraction

This page contains the full source code of the zouzg/mybatis-generator-gui GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 55 files (199.5 KB), approximately 47.5k tokens, and a symbol index with 342 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!