别再羡慕别人了!教你如何轻松掌握IDEA插件开发,成为编程高手!(三)-核心代码篇

✨这里是第七人格的博客✨小七,欢迎您的到来~✨

🍅系列专栏:实战🍅

✈️本篇内容: 核心代码实现✈️

🍱本篇收录完整代码地址:gitee.com/diqirenge/i...

楔子

上一章我们完成了UI的设计和开发,为我们的插件捏造好了身体,接下来,我们将完成数据库操作和代码生成功能,最好能一发入魂,嘿嘿~~~(✿◡‿◡)

DB操作

分支名称

231030-52javaee.com-BuildDb

仓库地址

gitee.com/diqirenge/i...

分支描述

编写db操作相关功能

代码实现

在build.gradle中的添加MySQL依赖,并且刷新依赖

gradle 复制代码
dependencies {
  implementation 'mysql:mysql-connector-java:8.0.16'
}

新建DBUtils工具类

java 复制代码
/**
 * db操作工具类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class DBUtils {

    /**
     * 数据库地址
     */
    private String host;
    /**
     * 端口号
     */
    private Integer port;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 数据库名称
     */
    private String database;

    /**
     * 配置
     */
    private Properties properties;

    public DBUtils(String host, Integer port, String username, String password, String database) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
        this.database = database;

        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e.getMessage(), e);
        }

        properties = new Properties();
        properties.put("user", this.username);
        properties.put("password", this.password);
        properties.setProperty("remarks", "true");
        properties.put("useInformationSchema", "true");
    }
 }

实现[测试连接信息]功能

工具类新增连接方法

java 复制代码
/**
 * 获取数据库连接
 *
 * @return {@link Connection}
 */
public Connection getConnection() {
    try {
        return DriverManager.getConnection("jdbc:mysql://" + this.host + ":" + this.port + "?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8", properties);
    } catch (SQLException e) {
        throw new RuntimeException(e.getMessage(), e);
    }
}
java 复制代码
/**
 * 测试连接信息
 *
 * @return {@link String}
 */
public String testDatabase() {
    Connection conn = getConnection();

    try {
        PreparedStatement preparedStatement = conn.prepareStatement("SELECT VERSION() AS MYSQL_VERSION");
        ResultSet resultSet;
        resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            return resultSet.getString("MYSQL_VERSION");
        }
    } catch (SQLException e) {
        throw new RuntimeException(e.getMessage(), e);
    } finally {
        closeConnection(conn);
    }
    return "未知错误";
}

UI修改监听测试按钮

java 复制代码
private void listenTestButton() {
    this.testButton.addActionListener(e -> {
        // 测试数据库连接
        try {
            if (checkRequireDbParam(project)) {
                return;
            }
            // 连接数据库
            DBUtils dbHelper = new DBUtils(this.localhost.getText(), Integer.parseInt(this.port.getText()), this.username.getText(), String.valueOf(this.password.getPassword()), this.database.getText());
            String mysqlVersion = dbHelper.testDatabase();
            Messages.showInfoMessage(project, "数据库连接成功! \r\n数据库版本: " + mysqlVersion, "连接成功");
        } catch (Exception exception) {
            Messages.showWarningDialog(project, "数据库连接错误,请检查配置." + exception.getMessage(), "Error");
        }
    });
}

测试

测试连接成功

实现[查询数据库表]功能

工具类新增查询表方法

java 复制代码
/**
 * 通过database,获取所有的表名
 *
 * @param database 数据库名称
 * @return {@link List}<{@link String}> 表名称集合
 */
public List<String> getAllTableName(String database) {
    this.database = database;
    Connection conn = getConnection(this.database);
    try {
        DatabaseMetaData metaData = conn.getMetaData();
        ResultSet rs = metaData.getTables(this.database, this.database, "%", new String[]{"TABLE"});
        List<String> ls = new ArrayList<>();
        while (rs.next()) {
            String s = rs.getString("TABLE_NAME");
            ls.add(s);
        }
        return ls;
    } catch (SQLException e) {
        throw new RuntimeException(e.getMessage(), e);
    } finally {
        closeConnection(conn);
    }
}
java 复制代码
/**
 * 通过表名称,模糊查询所有相似的表
 *
 * @param tableName 数据库名称
 * @return {@link List}<{@link String}> 表名称集合
 */
public List<String> getResembleTableName(String tableName) {
    Connection conn = getConnection(this.database);
    try {
        DatabaseMetaData metaData = conn.getMetaData();
        ResultSet rs = metaData.getTables(this.database, this.database, "%" + tableName + "%", new String[]{"TABLE"});
        List<String> ls = new ArrayList<>();
        while (rs.next()) {
            String s = rs.getString("TABLE_NAME");
            ls.add(s);
        }
        return ls;
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    } finally {
        closeConnection(conn);
    }
}

UI修改[监听查询数据库表按钮]

java 复制代码
// 查询的时候需要先把缓存置空
clearCache();
// 查询数据库表
List<String> tableList = getTableByDb();
// 画表
drawTable(tableList);
java 复制代码
private void clearCache() {
    // 清除UI缓存
    this.tableNames = new HashSet<>();
}

private List<String> getTableByDb() {
    DBUtils dbHelper = new DBUtils(this.localhost.getText(), Integer.parseInt(this.port.getText()), this.username.getText(), String.valueOf(this.password.getPassword()), this.database.getText());
    return !"".equals(this.tablename.getText())
            // 模糊查询表名
            ? dbHelper.getResembleTableName(this.tablename.getText())
            // 查询所有的表名
            : dbHelper.getAllTableName(this.database.getText());
}

private void drawTable(List<String> tableList) {
    String[] title = {"序号", "表名"};
    Object[][] data = new Object[tableList.size()][2];
    for (int i = 0; i < tableList.size(); i++) {
        data[i][1] = tableList.get(i);
    }

    table1.setModel(new DefaultTableModel(data, title));
    TableColumn tc = table1.getColumnModel().getColumn(0);
    tc.setCellRenderer(table1.getDefaultRenderer(Boolean.class));
    tc.setCellEditor(new DefaultCellEditor(new JCheckBox()));
    tc.setCellEditor(table1.getDefaultEditor(Boolean.class));
    tc.setMaxWidth(200);
}

测试

查询所有数据库表信息

模糊查询数据库表信息

去掉[监听鼠标点击表格]提示框

java 复制代码
/**
 * 监听鼠标点击表格
 */
private void listenTableMouseClicked() {
    this.table1.addMouseListener(new MouseAdapter() {
        // 选择表
        @Override
        public void mouseClicked(MouseEvent e) {
            if (1 == e.getClickCount()) {
                int rowIdx = table1.rowAtPoint(e.getPoint());
                Boolean flag = (Boolean) table1.getValueAt(rowIdx, 0);
                if (null != flag && flag) {
                    tableNames.add(table1.getValueAt(rowIdx, 1).toString());
                } else {
                    tableNames.remove(table1.getValueAt(rowIdx, 1).toString());
                }
            }
        }
    });
}

✨求点赞、关注加收藏。你的一键三连,是对小七写作最大的动力~✨

代码生成

写代码之前,先简单的梳理一下我们需要做的事情:从数据库元数据得到我们想要的数据,映射到我们插件自己的业务模型中,然后通过这些模型,再根据模版生成对应的代码,当然这些配置最好能够持久化。

基于以上思考,我们有了以下思维导图:

分支名称

231030-52javaee.com-GenerateCodeCore

仓库地址

gitee.com/diqirenge/i...

分支描述

编写代码生成核心代码

代码实现

模板引擎有很多,都是大同小异,我们这里选择freemarker来做。

添加依赖

在build.gradle中的添加freemarker依赖

gradle 复制代码
dependencies {
  implementation 'mysql:mysql-connector-java:8.0.16'
  implementation 'org.freemarker:freemarker:2.3.28'
}

数据库元数据

元数据 - 表

java 复制代码
/**
 * 元数据 - 表
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class Table {

    /**
     * 描述
     */
    private String comment;
    /**
     * 名称
     */
    private String name;
    /**
     * 列集合
     */
    private List<Column> columns;

    public Table(String comment, String name, List<Column> columns) {
        this.comment = comment;
        this.name = name;
        this.columns = columns;
    }

    public String getName() {
        return name;
    }

    public String getComment() {
        return comment;
    }

    public List<Column> getColumns() {
        return columns;
    }

}

元数据 - 列

java 复制代码
/**
 * 元数据 - 列
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class Column {

    /**
     * 描述
     */
    private String comment;
    /**
     * 名称
     */
    private String name;
    /**
     * 类型
     */
    private int type;
    /**
     * 是否是主键
     */
    private boolean id;

    public Column(String comment, String name, int type) {
        this.comment = comment;
        this.name = name;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public String getComment() {
        return comment;
    }

    public boolean isId() {
        return id;
    }

    public int getType() {
        return type;
    }

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

}

元数据 - 字段

java 复制代码
/**
 * 元数据 - 字段
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class Field {

    /**
     * 描述
     */
    private String comment;
    /**
     * 列名
     */
    private String columnName;
    /**
     * 对应的类型
     */
    private Class<?> type;
    /**
     * 是否是主键
     */
    private boolean id;


    public Field(String comment, Class<?> type, String columnName) {
        this.comment = comment;
        this.type = type;
        this.columnName = columnName;
    }

    public String getComment() {
        return comment;
    }

    public String getTypeName() {
        return type.getName();
    }

    public String getTypeSimpleName() {
        return type.getSimpleName();
    }

    public String getColumnName() {
        return columnName;
    }

    public String getName() {
        String str = columnName;
        return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, str);
    }

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

    public boolean isId() {
        return id;
    }

    /**
     * 自动导入
     * 
     * @return boolean
     */
    public boolean isImport() {
        String typeName = getTypeName();
        return !type.isPrimitive() && !"java.lang".equals(StringUtils.substringBeforeLast(typeName, "."));
    }

}

业务模型

基础业务模型

java 复制代码
/**
 * 基础业务模型
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public abstract class Base {

    /**
     * 类型
     */
    private int type;
    /**
     * 描述
     */
    private String comment;
    /**
     * 名字
     */
    private String name;

    public Base(String comment, String name) {
        this.comment = comment;
        this.name = name;
    }

    public String getPackage() {
        String str = StringUtils.substringAfterLast(name, "java/");
        if (!"".equals(str)) {
            str = str.substring(0, str.lastIndexOf(getSimpleName()) - 1);
        }
        return str.replaceAll("/", ".");
    }

    /**
     * 子类实现这个接口,返回一个Set,里面是导入的包名
     * 
     * @return {@link Set}<{@link String}>
     */
    public abstract Set<String> getImports();

    public String getSimpleName() {
        return name.lastIndexOf("/") == -1 ? name : StringUtils.substringAfterLast(name, "/");
    }

    public String getVarName() {
        return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, getSimpleName());
    }

    public String getName() {
        return name;
    }

    public String getMapperName() {
        String str = StringUtils.substringAfterLast(name, "java/");
        return str.replaceAll("/", ".");
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getComment() {
        return comment;
    }

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

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

业务模型-实体

java 复制代码
/**
 * 业务模型-实体
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class Entity extends Base {

    private String tableName;
    private List<Field> fields;

    public Entity(String comment, String name, String tableName, List<Field> fields) {
        super(comment, name);
        this.tableName = tableName;
        this.fields = fields;
    }

    public List<Field> getFields() {
        return fields;
    }

    public String getTableName() {
        return tableName;
    }

    @Override
    public Set<String> getImports() {
        Set<String> imports = new HashSet<>();
        List<Field> fields = getFields();
        for (Field field : fields) {
            if (field.isImport()) {
                imports.add(field.getTypeName());
            }
        }
        return imports;
    }

}

业务模型-mapper

java 复制代码
/**
 * 业务模型-mapper
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class Mapper extends Base {

    private Entity entity;

    public Mapper(String comment, String name, Entity entity) {
        super(comment, name);
        this.entity = entity;
    }

    public Entity getModel() {
        return entity;
    }

    @Override
    public Set<String> getImports() {
        Set<String> imports = new HashSet<>();
        imports.add(entity.getPackage() + "." + entity.getSimpleName());
        List<Field> fields = entity.getFields();
        for (Field field : fields) {
            if (field.isId() && field.isImport()) {
                imports.add(field.getTypeName());
                break;
            }
        }
        return imports;
    }

}

Db配置上下文

java 复制代码
/**
 * Db配置上下文
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class DbConfig {
    /**
     * 用户
     */
    private String user;

    /**
     * 密码
     */
    private String password;

    /**
     * 项目名称
     */
    private String projectName;

    /**
     * 类路径
     */
    private String classpath;


    /**
     * 表名集合
     */
    private Set<String> tableNames = new LinkedHashSet<>();


    /**
     * entity生成路径
     */
    private String entityPath;

    /**
     * mapper生成路径
     */
    private String mapperPath;


    /**
     * xml生成路径
     */
    private String xmlPath;

    /**
     * 数据库连接地址
     */
    private String host;

    /**
     * 端口
     */
    private String port;

    /**
     * 库
     */
    private String database;
    /**
     * 模版路径
     */
    private String templateUrl;

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

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

    public String getProjectName() {
        return projectName;
    }

    public void setProjectName(String projectName) {
        this.projectName = projectName;
    }

    public String getClasspath() {
        return classpath;
    }

    public void setClasspath(String classpath) {
        this.classpath = classpath;
    }

    public Set<String> getTableNames() {
        return tableNames;
    }

    public void setTableNames(Set<String> tableNames) {
        this.tableNames = tableNames;
    }

    public String getEntityPath() {
        return entityPath;
    }

    public void setEntityPath(String entityPath) {
        this.entityPath = entityPath;
    }

    public String getMapperPath() {
        return mapperPath;
    }

    public void setMapperPath(String mapperPath) {
        this.mapperPath = mapperPath;
    }

    public String getXmlPath() {
        return xmlPath;
    }

    public void setXmlPath(String xmlPath) {
        this.xmlPath = xmlPath;
    }

    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 getDatabase() {
        return database;
    }

    public void setDatabase(String database) {
        this.database = database;
    }

    public String getTemplateUrl() {
        return templateUrl;
    }

    public void setTemplateUrl(String templateUrl) {
        this.templateUrl = templateUrl;
    }
}

代码生成-上下文

java 复制代码
/**
 * 代码生成-上下文
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class CodeGenContext {

    /**
     * entity包路径
     */
    private String entityPackage;
    /**
     * mapper包路径
     */
    private String mapperPackage;
    /**
     * xml路径
     */
    private String xmlDir;
    /**
     * 模版路径
     */
    private String templateUrl;

    /**
     * 表集合
     */
    private List<Table> tables;

    public String getEntityPackage() {
        return entityPackage;
    }

    public void setEntityPackage(String entityPackage) {
        this.entityPackage = entityPackage;
    }

    public String getMapperPackage() {
        return mapperPackage;
    }

    public void setMapperPackage(String mapperPackage) {
        this.mapperPackage = mapperPackage;
    }

    public String getXmlDir() {
        return xmlDir;
    }

    public void setXmlDir(String xmlDir) {
        this.xmlDir = xmlDir;
    }

    public List<Table> getTables() {
        return tables;
    }

    public void setTables(List<Table> tables) {
        this.tables = tables;
    }

    public String getTemplateUrl() {
        return templateUrl;
    }

    public void setTemplateUrl(String templateUrl) {
        this.templateUrl = templateUrl;
    }
}

类型转换工具类

java 复制代码
/**
 * 类型转换工具类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class JavaType {

    private static LinkedHashMap<JDBCType, Class> map = new LinkedHashMap<>();

    static {
        //字符串类型
        map.put(JDBCType.VARCHAR, String.class);
        map.put(JDBCType.LONGVARCHAR, String.class);
        map.put(JDBCType.CHAR, String.class);
        //整数类型
        map.put(JDBCType.INTEGER, Integer.class);
        map.put(JDBCType.BIGINT, Long.class);
        map.put(JDBCType.SMALLINT, Integer.class);
        map.put(JDBCType.TINYINT, Integer.class);
        //浮点类型
        map.put(JDBCType.FLOAT, Float.class);
        map.put(JDBCType.DOUBLE, Double.class);
        map.put(JDBCType.DECIMAL, BigDecimal.class);
        //其他类型
        map.put(JDBCType.BOOLEAN, Boolean.class);
        map.put(JDBCType.DATE, LocalDateTime.class);
        map.put(JDBCType.TIME, LocalDateTime.class);
        map.put(JDBCType.TIMESTAMP, LocalDateTime.class);
        map.put(JDBCType.BIT, boolean.class);
    }

    public static Class convertType(int sqlType) {
        return map.getOrDefault(JDBCType.valueOf(sqlType), Object.class);
    }

}

代码生成器接口

java 复制代码
/**
 * 代码生成器接口
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public interface ICodeGenerator {

   	/**
     * 生成代码
     * @param project 工程
     * @param codeGenContext 代码生成上下文
     */
    void generation(Project project, CodeGenContext codeGenContext);

}

抽象的代码生成器

java 复制代码
/**
 * 抽象的代码生成器
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public abstract class AbstractCodeGenerator implements ICodeGenerator {

    @Override
    public void generation(Project project, CodeGenContext codeGenContext) {
        doGenerate(project, codeGenContext);
    }

    /**
     * 真正的生成方法,交给子类实现
     *
     * @param project 工程
     * @param codeGenContext 代码生成上下文
     */
    protected abstract void doGenerate(Project project, CodeGenContext codeGenContext);

    public void writeFile(Project project, String packageName, String name, String ftl, Object dataModel, Boolean useLocalTemplate) {
        VirtualFile virtualFile;
        try {
            virtualFile = createPackageDir(packageName).createChildData(project, name);
            StringWriter stringWriter = new StringWriter();
            Template template = TemplateFactory.getInstance(ftl, useLocalTemplate);
            template.process(dataModel, stringWriter);
            virtualFile.setBinaryContent(stringWriter.toString().getBytes(StandardCharsets.UTF_8));
        } catch (IOException | TemplateException e) {
            throw new RuntimeException(e);
        }
    }


    private static VirtualFile createPackageDir(String packageName) {
        String path = FileUtil.toSystemIndependentName(StringUtil.replace(packageName, ".", "/"));
        new File(path).mkdirs();
        return LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
    }

}

模板工厂

JAVA 复制代码
/**
 * 模板工厂
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class TemplateFactory {

    private TemplateFactory() {
    }

    private static String ENCODING = "UTF-8";

    /**
     * 内置模板默认路径
     */
    private static FreemarkerConfiguration FREEMARKER = new FreemarkerConfiguration("/template");

    public static Template getInstance(String ftl, Boolean useLocalTemplate) throws IOException {
        return useLocalTemplate ? FREEMARKER.getTemplate(ftl, ENCODING) : getCustomTemplate(ftl);
    }

    private static Template getCustomTemplate(String ftl) throws IOException {

        String substring = ftl.substring(0, ftl.lastIndexOf("/"));
        String substring1 = ftl.substring(ftl.lastIndexOf("/", ftl.length()));

        Configuration configuration = new Configuration(Configuration.getVersion());
        FileTemplateLoader fileTemplateLoader = new FileTemplateLoader(new File(substring));
        configuration.setTemplateLoader(fileTemplateLoader);

        return configuration.getTemplate(substring1, ENCODING);
    }


    static class FreemarkerConfiguration extends Configuration {
        public FreemarkerConfiguration(String basePackagePath) {
            super(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            setDefaultEncoding(ENCODING);
            setClassForTemplateLoading(getClass(), basePackagePath);
        }
    }

}

代码生成器工厂

java 复制代码
/**
 * 代码生成器工厂
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class CodeGeneratorFactory {

    private CodeGeneratorFactory() {
    }

    private static final LinkedHashMap<Boolean, ICodeGenerator> MAP = new LinkedHashMap<>();

    static {
        // 默认使用内置模板
        MAP.put(true, new CodeGeneratorImpl());
        MAP.put(false, new CustomCodeGeneratorImpl());
    }

    public static ICodeGenerator instance(CodeGenContext codeGenContext) {
        return MAP.get(StringUtils.isBlank(codeGenContext.getTemplateUrl()));
    }

}

生成策略

JAVA 复制代码
/**
 * 默认生成策略
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class CodeGeneratorImpl extends AbstractCodeGenerator {

    @Override
    protected void doGenerate(Project project, CodeGenContext codeGenContext) {

        List<Table> tables = codeGenContext.getTables();
        for (Table table : tables) {
            List<Column> columns = table.getColumns();
            List<Field> fields = new ArrayList<>();

            for (Column column : columns) {
                Field field = new Field(column.getComment(), JavaType.convertType(column.getType()), column.getName());
                field.setId(column.isId());
                fields.add(field);
            }

            // 生成Entity
            Entity entity = new Entity(table.getComment(), codeGenContext.getEntityPackage() + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table.getName()), table.getName(), fields);
            // 生成Mapper
            Mapper mapper = new Mapper(table.getComment(), codeGenContext.getXmlDir() + "I" + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table.getName()) + "Mapper", entity);

            writeFile(project, codeGenContext.getEntityPackage(), entity.getSimpleName() + ".java", "entity.ftl", entity, Boolean.TRUE);
            writeFile(project, codeGenContext.getMapperPackage(), mapper.getSimpleName() + ".java", "dao.ftl", mapper, Boolean.TRUE);
            writeFile(project, codeGenContext.getXmlDir(), mapper.getModel().getSimpleName() + "Mapper.xml", "mapper.ftl", mapper, Boolean.TRUE);

        }

    }

}
java 复制代码
/**
 * 自定义模版生成策略
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/10/30
 */
public class CustomCodeGeneratorImpl extends AbstractCodeGenerator {

    @Override
    protected void doGenerate(Project project, CodeGenContext codeGenContext) {

        List<Table> tables = codeGenContext.getTables();
        for (Table table : tables) {
            List<Column> columns = table.getColumns();
            List<Field> fields = new ArrayList<>();

            for (Column column : columns) {
                Field field = new Field(column.getComment(), JavaType.convertType(column.getType()), column.getName());
                field.setId(column.isId());
                fields.add(field);
            }

            // 生成Entity
            Entity entity = new Entity(table.getComment(), codeGenContext.getEntityPackage() + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table.getName()), table.getName(), fields);
            // 生成Mapper
            Mapper mapper = new Mapper(table.getComment(), codeGenContext.getXmlDir() + "I" + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table.getName()) + "Mapper", entity);

            writeFile(project, codeGenContext.getEntityPackage(), entity.getSimpleName() + ".java", codeGenContext.getTemplateUrl() + "/entity.ftl", entity, Boolean.FALSE);

            writeFile(project, codeGenContext.getMapperPackage(), mapper.getSimpleName() + ".java", codeGenContext.getTemplateUrl() + "/dao.ftl", mapper, Boolean.FALSE);

            writeFile(project, codeGenContext.getXmlDir(), mapper.getModel().getSimpleName() + "Mapper.xml", codeGenContext.getTemplateUrl() + "/mapper.ftl", mapper, Boolean.FALSE);

        }

    }

}

修改UI类

新增参数

java 复制代码
/**
 * db配置上下文
 */
private DbConfig config;

修改构造方法

java 复制代码
public CodeGenerateUi(Project project) {
    // 初始化数据
    this.project = project;
    this.projectName.setText(project.getName());
    this.classpath.setText(project.getBasePath());
    config = new DbConfig();

    this.database.setText(config.getDatabase());
    this.localhost.setText(config.getHost());
    this.port.setText(config.getPort());
    this.entityUrl.setText(config.getEntityPath());
    this.mapperUrl.setText(config.getMapperPath());
    this.xmlUrl.setText(config.getXmlPath());
    this.username.setText(config.getUser());

    // 增加监听
    addListener(project);
}

修改[监听代码生成按钮]方法

java 复制代码
/**
 * 监听代码生成按钮
 */
private void listenGenerateButton() {
    this.generateButton.addActionListener(e -> {
        try {
            if (checkRequireGenerateParam(project)) {
                return;
            }
            // 生成代码
            // 设置配置
            config.setUser(this.username.getText());
            config.setPassword(new String(this.password.getPassword()));
            config.setProjectName(this.projectName.getText());
            config.setClasspath(this.classpath.getText());
            config.setDatabase(this.database.getText());
            config.setHost(this.localhost.getText());
            config.setPort(this.port.getText() != null ? this.port.getText() : "3306");
            config.setEntityPath(this.entityUrl.getText());
            config.setMapperPath(this.mapperUrl.getText());
            config.setXmlPath(this.xmlUrl.getText());
            config.setTemplateUrl(this.templateUrl.getText());

            // 组装代码生产上下文
            CodeGenContext codeGenContext = new CodeGenContext();
            codeGenContext.setEntityPackage(config.getEntityPath() + "/entity/");
            codeGenContext.setMapperPackage(config.getMapperPath() + "/mapper/");
            codeGenContext.setXmlDir(config.getXmlPath() + "/mapper/");
            codeGenContext.setTemplateUrl(config.getTemplateUrl());

            // 链接DB
            DBUtils dbHelper = new DBUtils(config.getHost(), Integer.parseInt(config.getPort()), config.getUser(), config.getPassword(), config.getDatabase());
            List<Table> tables = new ArrayList<>();
            for (String tableName : tableNames) {
                tables.add(dbHelper.getTable(tableName));
            }
            codeGenContext.setTables(tables);

            // 这里必须要放到UI的线程中,不然打包成插件后会报错
            ApplicationManager.getApplication().runWriteAction(() ->
                    CodeGeneratorFactory.instance(codeGenContext).generation(project, codeGenContext));

            Messages.showWarningDialog(project, "代码已生成", "Success");
        } catch (Exception ex) {
            Messages.showWarningDialog(project, "代码生成失败:" + ex.getMessage(), "Error");
        }
    });
}

添加模板

在resources下新建template,并添加模板

测试

1、内置模板生成成功

2、自定义模板生成成功

✨求点赞、关注加收藏。你的一键三连,是对小七写作最大的动力~✨

相关推荐
写bug写bug13 分钟前
手把手教你使用JConsole
java·后端·程序员
异常君14 分钟前
Java 中 try-catch 的性能真相:全面分析与最佳实践
java·面试·代码规范
苏三说技术17 分钟前
给你1亿的Redis key,如何高效统计?
后端
JohnYan40 分钟前
工作笔记- 记一次MySQL数据移植表空间错误排除
数据库·后端·mysql
程序员清风1 小时前
阿里二面:Kafka 消费者消费消息慢(10 多分钟),会对 Kafka 有什么影响?
java·后端·面试
幼稚园的山代王1 小时前
Prompt Enginering(提示工程)先进技术
java·人工智能·ai·chatgpt·langchain·prompt
周某某~1 小时前
二.单例模式‌
java·单例模式·设计模式
摸鱼仙人~1 小时前
深入理解Java单例模式:确保类只有一个实例
java·javascript·单例模式
CodeSheep1 小时前
宇树科技,改名了!
前端·后端·程序员
hstar95272 小时前
三十五、面向对象底层逻辑-Spring MVC中AbstractXlsxStreamingView的设计
java·后端·spring·设计模式·架构·mvc