One click generation of target class file based on FreeMarker template configuration

1. Preface

There are a lot of duplicate code writing (copy and paste) when the business layer service and control layer controller create files. For reusable code writing, you can extract customized freemaker templates to generate target files to reduce repetitive work. Java is written based on freemaker template and can output specific template files, as shown in Figure 1.1, freemaker template usage example. Java can maintain data, freemaker template can focus on data presentation and output template style files.

Reusable code templates are configured here to realize one click generation of duplicate code file classes. Generate and output target files based on freemaker template technology.

Only the function is realized here, which can be generated by running the main main function with one click, without undertaking the front-end page. (reusable code templates: Entity.java, EntityDao.java, EntityService.java, EntityServiceImpl.java, etc.)

Figure 1.1. Example of freemaker template

2. Design and Implementation

2.1 realization of functions

Generate the corresponding entity class, persistence class, business interface and business implementation class according to the data table.

2.2 application scenarios

During project creation or project iteration, maintain the business class, control layer, persistence layer, entity class and other files related to the table when extending the design of a new table.

2.3 design realization

Maven project management relies on the interactive database to read the specified table design and generate the target file according to the Template template configuration.

3. Effect demonstration

Create a Maven project here, introduce freemaker dependency, and configure the Template file in the project to the entity Template entity ftl and business implementation Template entityserviceimpl ftl as an example. (the Template file extension is ftl.)

In table xxl_job_qrtz_trigger_group as an example, generate corresponding entity class, persistence layer and business layer class files.
The table structure is as follows

CREATE TABLE `xxl_job_qrtz_trigger_group` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`app_name` VARCHAR(64) NOT NULL COMMENT 'Actuator AppName' COLLATE 'utf8_general_ci',
	`title` VARCHAR(12) NOT NULL COMMENT 'Actuator name' COLLATE 'utf8_general_ci',
	`order` TINYINT(4) NOT NULL DEFAULT '0' COMMENT 'sort',
	`address_type` TINYINT(4) NOT NULL DEFAULT '0' COMMENT 'Actuator address type: 0=Automatic registration, 1=Manual entry',
	`address_list` VARCHAR(200) NULL DEFAULT NULL COMMENT 'Actuator address list, multiple addresses separated by commas' COLLATE 'utf8_general_ci',
	PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;

3.1 entity class template configuration and template file generation

3.1.1 template file entity ftl
Encapsulates the underline hump conversion function dashedToCamel().

Freemaker built-in function reference Freemaker built-in function
Refer to cap here_ first,uncap_first and other functions.

cap_first: capitalize the first letter of the first word in the string
uncap_first: the first letter of the first word in the string is lowercase

<#assign aDate = .now?date>
<#function dashedToCamel(s)>
	<#return s
	?replace('(^_+)|(_+$)', '', 'r')
	?replace('\\_+(\\w)?', ' $1', 'r')
	?replace('([A-Z])', ' $1', 'r')
	?capitalize
	?replace(' ' , '')
	?uncap_first
	>
</#function>
package pers.niaonao.generate.freemarker.entity;

import java.util.*;

/**
 * @description Entity class
 * @date ${aDate?iso_utc}
 * @author niaonao
 */
public class ${model.className} {

	private static final long serialVersionUID = 1L;

<#list model.columnsName?keys as column>
	/**
	 *   ${model.columnsName[column].columnComment!}
	 *  column: ${column}
	 */
	private ${model.columnsName[column].columnType!} ${dashedToCamel(model.columnsName[column].columnName)};
</#list>

<#list model.columnsName?keys as column>
	/**
	 *   ${model.columnsName[column].columnComment!}
	 *  column: ${column}
	 */
	public ${model.columnsName[column].columnType!} get${dashedToCamel(model.columnsName[column].columnName)?cap_first}(){
		return ${dashedToCamel(model.columnsName[column].columnName)};
	}
	public void set${dashedToCamel(model.columnsName[column].columnName)?cap_first} (${model.columnsName[column].columnType!} ${dashedToCamel(model.columnsName[column].columnName)}){
		this.${dashedToCamel(model.columnsName[column].columnName)} = ${dashedToCamel(model.columnsName[column].columnName)};
	}
</#list>

}

3.1.2 target file generation jobqrtztriggergroup java

package pers.niaonao.generate.freemarker.entity;

import java.util.*;

/**
 * @description Entity class
 * @date 2021-07-13
 * @author niaonao
 */
public class JobQrtzTriggerGroup {

	private static final long serialVersionUID = 1L;

	/**
	 *   Actuator address list, multiple addresses separated by commas
	 *  column: address_list
	 */
	private String addressList;
	/**
	 *   Actuator address type: 0 = automatic registration, 1 = manual entry
	 *  column: address_type
	 */
	private Integer addressType;
	/**
	 *   Actuator AppName
	 *  column: app_name
	 */
	private String appName;
	/**
	 *   
	 *  column: id
	 */
	private Integer id;
	/**
	 *   sort
	 *  column: order
	 */
	private Integer order;
	/**
	 *   Actuator name
	 *  column: title
	 */
	private String title;

	/**
	 *   Actuator address list, multiple addresses separated by commas
	 *  column: address_list
	 */
	public String getAddressList(){
		return addressList;
	}
	public void setAddressList (String addressList){
		this.addressList = addressList;
	}
	/**
	 *   Actuator address type: 0 = automatic registration, 1 = manual entry
	 *  column: address_type
	 */
	public Integer getAddressType(){
		return addressType;
	}
	public void setAddressType (Integer addressType){
		this.addressType = addressType;
	}
	/**
	 *   Actuator AppName
	 *  column: app_name
	 */
	public String getAppName(){
		return appName;
	}
	public void setAppName (String appName){
		this.appName = appName;
	}
	/**
	 *   
	 *  column: id
	 */
	public Integer getId(){
		return id;
	}
	public void setId (Integer id){
		this.id = id;
	}
	/**
	 *   sort
	 *  column: order
	 */
	public Integer getOrder(){
		return order;
	}
	public void setOrder (Integer order){
		this.order = order;
	}
	/**
	 *   Actuator name
	 *  column: title
	 */
	public String getTitle(){
		return title;
	}
	public void setTitle (String title){
		this.title = title;
	}

}

3.2 business implementation class template configuration and template file generation

3.2.1 template file entityserviceimpl ftl

<#assign aDate = .now?date>
package pers.niaonao.generate.freemarker.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pers.niaonao.generate.freemarker.dao.${model.className}Dao;
import pers.niaonao.generate.freemarker.entity.${model.className};

import java.util.List;

/**
 * @description Business layer implementation
 * @date ${aDate?iso_utc}
 * @author niaonao
 */
@Service
public class ${model.className}ServiceImpl implements ${model.className}Service {

	/**
	* Introduce persistence layer
	*/
	private ${model.className}Dao ${model.className?uncap_first }Dao;

	@Autowired
	public ${model.className}ServiceImpl(${model.className}Dao ${model.className?uncap_first }Dao) {
		this.${model.className?uncap_first }Dao = ${model.className?uncap_first }Dao;
	}

	public List<${model.className}> findAllList() {
		return ${model.className?uncap_first }Dao.findAllList();
	}
	public ${model.className} getById(Integer id) {
		return ${model.className?uncap_first }Dao.getById(id);
	}
}

3.2.2 generate the target file jobqrtztriggergroupserviceimpl java

package pers.niaonao.generate.freemarker.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pers.niaonao.generate.freemarker.dao.JobQrtzTriggerGroupDao;
import pers.niaonao.generate.freemarker.entity.JobQrtzTriggerGroup;

import java.util.List;

/**
 * @description Business layer implementation
 * @date 2021-07-13
 * @author niaonao
 */
@Service
public class JobQrtzTriggerGroupServiceImpl implements JobQrtzTriggerGroupService {

	/**
	* Introduce persistence layer
	*/
	private JobQrtzTriggerGroupDao jobQrtzTriggerGroupDao;

	@Autowired
	public JobQrtzTriggerGroupServiceImpl(JobQrtzTriggerGroupDao jobQrtzTriggerGroupDao) {
		this.jobQrtzTriggerGroupDao = jobQrtzTriggerGroupDao;
	}

	public List<JobQrtzTriggerGroup> findAllList() {
		return jobQrtzTriggerGroupDao.findAllList();
	}
	public JobQrtzTriggerGroup getById(Integer id) {
		return jobQrtzTriggerGroupDao.getById(id);
	}
}

4. Code implementation

Figure 4.1 project structure
  • The database demonstration script file is stored in the doc folder;
  • dao, entity and service packages are used as the target file generation paths of different templates;
  • The helper package contains the implementation of freemaker template configuration, template loading and target file generation. The main method entry is modelgenerator Main() method.
    • helper.constant maintains constant classes;
    • helper.enums maintains enumeration classes and configures the mapping management of template ID, template file path and generated target file path;
    • helper.template maintain template files;
    • helper.util maintenance tool class, where the function is realized to generate the corresponding business class file according to the table design, encapsulating the table field data type conversion tool class, etc;

4.1 new project configuration dependency

Create a new Maven project and configure the dependency principle
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>pers.niaonao</groupId>
    <artifactId>generate-code-template</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.3</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <!-- Database connection pool -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
        </dependency>

        <!-- Apache FreeMarker Template engine for generating generic text -->
        <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <!-- Open source tool library -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>
    </dependencies>
</project>

4.2 description of key methods for FreeMarker template configuration

Freemaker Configuration information can be configured in the Configuration instance or overwritten in the Template instance. Generally through Configuration Setter () method. It is generally recommended to configure in the Configuration instance, and it is not recommended to overwrite the Configuration in the Template instance.
Example:

    Configuration myCfg = new Configuration(Configuration.VERSION_2_3_30);
    myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
    myCfg.setDefaultEncoding("UTF-8");

Through template Process (...) method loads the template configuration output target file;

The specific template can be through configuration GetTemplate (...) get.

	/** 
	 * dataModel: java model Carry data to template
	 * out: Output to target file
	 * 
	 * String templateName = "Full path of template file ";
	 * Configuration configuration = new Configuration(Configuration.VERSION_2_3_30);
	 * Template template = configuration.getTemplate(templateName);
	 * template.process(dataModel, out);
	 */
    public void process(Object dataModel, Writer out) throws TemplateException, IOException {
        this.createProcessingEnvironment(dataModel, out, (ObjectWrapper)null).process();
    }

If you use template directly The process() method is wrong, you can manually configure the instance Environment and call the method process() to output the target file.

	Environment env = myTemplate.createProcessingEnvironment(root, out);
	env.setLocale(java.util.Locale.ITALY);
	env.setNumberFormat("0.####");
	env.process();  // process the template

4.3 description of main documents for function realization

4.3.1 enumeration class maintenance template file and target file generation path

GenerateTemplateEnum.java

package pers.niaonao.generate.freemarker.helper.enums;

/**
 * @description: Template enumeration class
 * @author niaonao
 **/
public enum GenerateTemplateEnum {

    /**
     * Enumeration values include template ID, template file and generation target path
     */
    GENERATE_MODEL("entity","entity.ftl", "/entity/"),
    GENERATE_DAO("entityDao","entityDao.ftl", "/dao/"),
    GENERATE_SERVICE("entityService","entityService.ftl", "/service/"),
    GENERATE_SERVICE_IMPL("entityServiceImpl","entityServiceImpl.ftl", "/service/");

    /**
     * code
     */
    private String code;
    /**
     * Generate target file path
     */
    private String targetDir;
    /**
     * template file
     */
    private String templateFtl;

    GenerateTemplateEnum(String code, String templateFtl, String targetDir) {
        this.code = code;
        this.templateFtl = templateFtl;
        this.targetDir = targetDir;
    }

    public String getCode() {
        return code;
    }

    public String getTargetDir() {
        return targetDir;
    }

    public String getTemplateFtl() {
        return templateFtl;
    }

    public static GenerateTemplateEnum getEnumValue(String code) {
        for (GenerateTemplateEnum constants : values()) {
            if (constants.getCode().equals(code)) {
                return constants;
            }
        }
        return null;
    }
}

4.3.2 table field data type conversion class
Converts a data table field data type to a Java data type.

DbDataTypeConvertUtil.java

package pers.niaonao.generate.freemarker.helper.util;

import java.util.Map;
import java.util.TreeMap;

/**
 * @description: Table field type conversion
 * @author niaonao
 **/
public class DbDataTypeConvertUtil {
    /**
     * Name to value
     */
    private static Map<String, String> jdbcTypes;

    static {
        jdbcTypes = new TreeMap<String, String>();
        jdbcTypes.put("varchar", "String");
        jdbcTypes.put("char", "String");
        jdbcTypes.put("longtext", "String");
        jdbcTypes.put("text", "String");
        jdbcTypes.put("blob", "java.lang.byte[]");
        jdbcTypes.put("text", "String");
        jdbcTypes.put("integer", "Long");
        jdbcTypes.put("int", "Integer");
        jdbcTypes.put("tinyint", "Integer");
        jdbcTypes.put("smallint", "Integer");
        jdbcTypes.put("mediumint", "Integer");
        jdbcTypes.put("bit", "Boolean");
        jdbcTypes.put("bigint", "Long");
        jdbcTypes.put("float", "Float");
        jdbcTypes.put("double", "Double");
        jdbcTypes.put("decimal", "BigDecimal");
        jdbcTypes.put("boolean", "Integer");
        jdbcTypes.put("date", "Date");
        jdbcTypes.put("time", "Date");
        jdbcTypes.put("datetime", "Date");
        jdbcTypes.put("timestamp", "Date");
        jdbcTypes.put("year", "Date");
    }
    public static String getJavaType(String sqlType) {
        return jdbcTypes.get(sqlType);
    }
}

4.3.3 data table field model encapsulation
Used to render field data information when freemaker template generates files
ColumnModel .java

package pers.niaonao.generate.freemarker.helper.util;

/**
 * @description: Table field model
 * @author niaonao
 **/
public class ColumnModel {
    /**
     * Field name
     */
    private String columnName;
    /**
     * Field data type
     */
    private String columnType;
    /**
     * Field description
     */
    private String columnComment;

    public String getColumnName() {
        return columnName;
    }

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

    public String getColumnType() {
        return columnType;
    }

    public void setColumnType(String columnType) {
        this.columnType = columnType;
    }

    public String getColumnComment() {
        return columnComment;
    }

    public void setColumnComment(String columnComment) {
        this.columnComment = columnComment;
    }
}

4.3.4 data sheet model encapsulation

TableModel.java

package pers.niaonao.generate.freemarker.helper.util;

import java.util.Map;

/**
 * @description Entity class Model
 * @author niaonao
 **/
public class TableModel {

    /**
     * entity Entity class name
     */
    private String className;
    /**
     * entity Table name
     */
    private String tableName;
    /**
     * Primary key field name
     */
    private String primaryKey;
    /**
     * Table field collection
     */
    private Map<String, ColumnModel> columnsName;

    public TableModel(String tableName, String primaryKey, String className, Map<String, ColumnModel> columnsName) {
        super();
        this.className = className;
        this.tableName = tableName;
        this.primaryKey = primaryKey;
        this.columnsName = columnsName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getTableName() {
        return tableName;
    }

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

    public String getPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(String primaryKey) {
        this.primaryKey = primaryKey;
    }

    public Map<String, ColumnModel> getColumnsName() {
        return columnsName;
    }

    public void setColumnsName(Map<String, ColumnModel> columnsName) {
        this.columnsName = columnsName;
    }
}

4.3.5 implementation of automatic generation of class files
(1) the generation method autoGenerateModel(String... tableNames) supports passing in multiple tables and traversing to generate corresponding business classes;
(2) initialize the configuration information method init() to maintain database information;
(3) freemaker Configuration instance Configuration information;
(4) configure the generated target file type, and extend and maintain according to the enumeration class;
(5) support the removal of business table prefix, such as XXX_ job_ The generated entity file is jobinfo Java instead of xxljobinfo java .
(6) read the data table design and convert it to the encapsulated model method generate(), and according to the model and template Process (...) generates the target file.

package pers.niaonao.generate.freemarker.helper;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.StringUtils;
import com.google.common.collect.ImmutableMap;
import freemarker.template.Configuration;
import freemarker.template.Template;
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.sql.DataSource;

import pers.niaonao.generate.freemarker.helper.constant.Global;
import pers.niaonao.generate.freemarker.helper.util.ColumnModel;
import pers.niaonao.generate.freemarker.helper.util.DbDataTypeConvertUtil;
import pers.niaonao.generate.freemarker.helper.util.TableModel;
import pers.niaonao.generate.freemarker.helper.enums.GenerateTemplateEnum;

/**
 * @description Template class automatic generation tool
 * freemarker Built in function reference document: http://freemarker.foofun.cn/ref_builtins_string.html
 * @author niaonao
 */
public class ModelGenerator {
    private static String jdbcUrl;
    private static String username;
    private static String password;
    private static String SHOW_TABLE_NAME = "show tables";
    private static String SHOW_COLUMN_INFO =
            "select column_name,column_comment,data_type,column_key from information_schema.columns where table_name = '${tableName}'";
    private final String TEMPLATE_NAME = "TEMPLATE_NAME";
    private final String FILE_NAME = "FILE_NAME";
    private final String REPLACE_TABLE_NAME = "${tableName}";
    private String courseFile;
    /**
     *
     */
    private Configuration cfg;
    /**
     * Remove prefix from business table
     */
    private static String[] removedTableNamePrefixes;
    /**
     * The generated file type corresponds to the template one by one
     */
    private List<String> generalTypeList;

    public ModelGenerator() {
    }

    /**
     * Load data source
     */
    public static DataSource getDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    /**
     * Initialize configuration information global variable
     * @throws IOException
     */
    public void init() throws IOException {
        // TODO database link information
        jdbcUrl = "jdbc:mysql://127.0.0.1:3306/xxlJob?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull";
        username = "root";
        password = "root";
        // Remove the service prefix of the table. Here, take the xxl service table as an example
        removedTableNamePrefixes = new String[]{"xxl_"};
        // Generate entity classes, dao files, business interface files, and business implementation classes
        this.generalTypeList =
                Arrays.asList(GenerateTemplateEnum.GENERATE_MODEL.getCode(),
                        GenerateTemplateEnum.GENERATE_DAO.getCode(),
                        GenerateTemplateEnum.GENERATE_SERVICE.getCode(),
                        GenerateTemplateEnum.GENERATE_SERVICE_IMPL.getCode());
        this.courseFile = (new File(Global.EMPTY)).getCanonicalPath();
        String pathName =
                new StringBuilder(this.courseFile)
                        .append(Global.FREEMARKER_TEMPLATE_DIR)
                        .toString();
        this.cfg = new Configuration(Configuration.VERSION_2_3_30);
        this.cfg.setDirectoryForTemplateLoading(new File(pathName));
    }

    /**
     * @description: Method of generating template class file
     * @param: tableNames
     * @return: void
     * @author: niaonao
     * @date: 2021/7/13
     */
    public void generate(String... tableNames) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        PreparedStatement columnPs = null;
        ResultSet resultSet = null;
        Object columnRs = null;

        try {
            DataSource dataSource = getDataSource();
            connection = dataSource.getConnection();
            preparedStatement = connection.prepareStatement(SHOW_TABLE_NAME);
            if (tableNames.length == 0) {
                resultSet = preparedStatement.executeQuery();

                while(resultSet.next()) {
                    String tbName = resultSet.getString(1);
                    columnPs = connection.prepareStatement(SHOW_COLUMN_INFO.replace(REPLACE_TABLE_NAME, tbName));
                    this.generateTable(columnPs, tbName);
                }
            } else {
                String[] var22 = tableNames;
                int var9 = tableNames.length;

                for(int var10 = 0; var10 < var9; ++var10) {
                    String tbName = var22[var10];
                    columnPs = connection.prepareStatement(SHOW_COLUMN_INFO.replace(REPLACE_TABLE_NAME, tbName));
                    this.generateTable(columnPs, tbName);
                }
            }
        } catch (Exception var20) {
            System.out.println(var20.getMessage());
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }

                if (preparedStatement != null) {
                    preparedStatement.close();
                }

                if (columnRs != null) {
                    ((ResultSet)columnRs).close();
                }

                if (columnPs != null) {
                    columnPs.close();
                }

                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException var19) {
                System.out.println(var19.getMessage());
            }

        }

    }

    /**
     * @description: Generate class files according to table design and template
     * @param: columnPs
     * @param: tbName
     * @return: void
     * @author: niaonao
     * @date: 2021/7/13
     */
    private void generateTable(PreparedStatement columnPs, String tbName) {
        System.out.println("Start processing data table:" + tbName);
        Map modelMap = new HashMap();
        ResultSet columnRs = null;

        try {
            String primaryKey = Global.EMPTY;
            Map<String, ColumnModel> colunms = new TreeMap();
            columnRs = columnPs.executeQuery();

            String generalType;
            String fileName;
            while(columnRs.next()) {
                String filed = columnRs.getString(1);
                String comment = columnRs.getString(2);
                generalType = columnRs.getString(3);
                String key = columnRs.getString(4);
                int endIndex = generalType.indexOf("(") > 0 ? generalType.indexOf("(") : generalType.length();
                fileName = DbDataTypeConvertUtil.getJavaType(generalType.substring(0, endIndex));
                if (!StringUtils.isEmpty(key) && "PRI".equals(key)) {
                    primaryKey = filed;
                }

                ColumnModel column = new ColumnModel();
                column.setColumnComment(comment);
                column.setColumnName(filed);
                column.setColumnType(fileName);
                colunms.put(filed, column);
            }

            TableModel em = new TableModel(tbName, primaryKey, toJavaClassStyle(tbName), colunms);
            modelMap.put("model", em);
            Iterator var17 = this.generalTypeList.iterator();

            while(var17.hasNext()) {
                generalType = (String)var17.next();
                Map<String, String> nameMap = this.getTemplateName(generalType, em.getClassName());
                String templateName = nameMap.get(TEMPLATE_NAME);
                fileName = nameMap.get(FILE_NAME);
                BufferedWriter modelBufferWriter = new BufferedWriter(new FileWriter(fileName));
                Template modelTemplate = this.cfg.getTemplate(templateName);
                modelTemplate.process(modelMap, modelBufferWriter);
            }

            System.out.println("Class file generation under business path is completed. Data table:" + tbName);
        } catch (Exception var15) {
            System.out.println("The class file generated under the business path is abnormal, " + var15.getMessage());
        }

    }

    /**
     * @description: Get template and class file generation path
     * @param: modelType
     * @param: className
     * @return: java.util.Map<java.lang.String,java.lang.String>
     * @author: niaonao
     * @date: 2021/7/13
     */
    private Map<String, String> getTemplateName(String modelType, String className) {
        String templateFtl = Global.EMPTY;
        String fileDir = Global.EMPTY;
        GenerateTemplateEnum[] var5 = GenerateTemplateEnum.values();
        int var6 = var5.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            GenerateTemplateEnum template = var5[var7];
            if (template.getCode().equals(modelType)) {
                templateFtl = template.getTemplateFtl();
                fileDir = this.getTargetDirByFtl(modelType, className);
                break;
            }
        }

        return ImmutableMap.of(TEMPLATE_NAME, templateFtl, FILE_NAME, fileDir);
    }

    /**
     * Return the specification file name according to the business layer
     * @param modelType
     * @param className
     * @return generate fileName
     */
    private String getTargetDirByFtl(String modelType, String className) {
        StringBuilder targetDirBuilder = new StringBuilder(this.courseFile).append(Global.FREEMARKER_RELATIVE_DIR);
        if (GenerateTemplateEnum.GENERATE_DAO.getCode().equals(modelType)) {
            return targetDirBuilder
                    .append(GenerateTemplateEnum.GENERATE_DAO.getTargetDir())
                    .append(className)
                    .append("Dao.java")
                    .toString();
        }
        if (GenerateTemplateEnum.GENERATE_SERVICE.getCode().equals(modelType)) {
            return targetDirBuilder
                    .append(GenerateTemplateEnum.GENERATE_SERVICE.getTargetDir())
                    .append(className)
                    .append("Service.java")
                    .toString();
        }
        if (GenerateTemplateEnum.GENERATE_SERVICE_IMPL.getCode().equals(modelType)) {
            return targetDirBuilder
                    .append(GenerateTemplateEnum.GENERATE_SERVICE_IMPL.getTargetDir())
                    .append(className)
                    .append("ServiceImpl.java")
                    .toString();
        }

        // if (GenerateTemplateEnum.GENERATE_MODEL.getCode().equals(modelType)) {
        return targetDirBuilder
                .append(GenerateTemplateEnum.GENERATE_MODEL.getTargetDir())
                .append(className)
                .append(".java")
                .toString();
    }

    private static String toJavaClassStyle(String str) {
        if (removedTableNamePrefixes != null) {
            String[] var1 = removedTableNamePrefixes;
            int var2 = var1.length;

            for(int var3 = 0; var3 < var2; ++var3) {
                String prefix = var1[var3];
                if (str.startsWith(prefix)) {
                    str = str.replaceFirst(prefix, "");
                    break;
                }
            }
        }

        return underlineToCamelHump(str);
    }

    /**
     * @description: Double hump
     * @param: str
     * @return: java.lang.String
     * @author: niaonao
     * @date: 2021/7/13
     */
    private static String underlineToCamelHump(String str) {
        Matcher matcher = Pattern.compile("_[a-z]").matcher(str);
        StringBuilder builder = new StringBuilder(str);

        for(int i = 0; matcher.find(); ++i) {
            builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase());
        }

        builder.replace(0, 1, String.valueOf(Character.toUpperCase(builder.charAt(0))));
        return builder.toString();
    }

    /**
     * @description: Generate class files from tables
     * @param: tableNames
     * @return: void
     * @author: niaonao
     * @date: 2021/7/13
     */
    public static void autoGenerateModel(String... tableNames) {
        ModelGenerator generator = new ModelGenerator();

        try {
            generator.init();
            generator.generate(tableNames);
        } catch (Exception var3) {
            System.out.println(var3.getMessage());
        }

    }

    /*public static void main(String[] args) {
        autoGenerateModel("xxl_job_qrtz_trigger_group", "xxl_job_qrtz_trigger_info");
    }*/
}

In table xxl_job_qrtz_trigger_group,xxl_job_qrtz_trigger_info as an example, the rendering of the target business file generated according to the configuration template is as follows.

Figure 4.2 project structure

Figure 4.3. Target file generation diagram

5. Project source code

Source code: https://gitee.com/niaonao/GenerateCodeTemplate
Documentation: for more usage, please refer to freemaker's Chinese documentation, http://freemarker.foofun.cn/index.html

Powered By niaonao

Keywords: Java FreeMarker IDE

Added by foolygoofy on Mon, 17 Jan 2022 12:09:25 +0200