org.apache.playframework.generator.mybatisplus.AutoGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.playframework.generator.mybatisplus.AutoGenerator.java

Source

/**
 * Copyright (c) 2011-2014, hubin (jobob@qq.com).
 * <p>
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 org.apache.playframework.generator.mybatisplus;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.enums.DBType;
import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.toolkit.SqlReservedWords;
import com.baomidou.mybatisplus.toolkit.StringUtils;

/**
 * <p>
 * ?
 * </p>
 *
 * @author hubin yanghu
 * @Date 2016-06-12
 */
public class AutoGenerator {

    protected ConfigGenerator config;

    public ConfigGenerator getConfig() {
        return config;
    }

    public void setConfig(ConfigGenerator config) {
        this.config = config;
    }

    public AutoGenerator() {

    }

    public AutoGenerator(ConfigGenerator config) {
        this.config = config;
    }

    protected static String PATH_ENTITY = null;
    protected static String PATH_MAPPER = null;
    protected static String PATH_XML = null;
    protected static String PATH_SERVICE = null;
    protected static String PATH_SERVICE_IMPL = null;
    protected static String PATH_CONTROLLER_IMPL = null;

    protected static boolean FILE_OVERRIDE = false;

    protected static final String JAVA_SUFFIX = ".java";
    protected static final String XML_SUFFIX = ".xml";

    /**
     * run 
     */
    public static void run(ConfigGenerator config) {
        if (config == null) {
            throw new MybatisPlusException(" ConfigGenerator is null. ");
        } else if (config.getIdType() == null) {
            throw new MybatisPlusException("ConfigGenerator IdType is null");
        }

        /**
         * ?
         */
        File gf = new File(config.getSaveDir());
        if (!gf.exists()) {
            gf.mkdirs();
        }

        /**
         * 
         */
        String saveDir = gf.getPath();
        PATH_ENTITY = getFilePath(saveDir, getPathFromPackageName(config.getEntityPackage()));
        PATH_MAPPER = getFilePath(saveDir, getPathFromPackageName(config.getMapperPackage()));
        PATH_XML = getFilePath(saveDir, getPathFromPackageName(config.getXmlPackage()));
        PATH_SERVICE = getFilePath(saveDir, getPathFromPackageName(config.getServicePackage()));
        PATH_SERVICE_IMPL = getFilePath(saveDir, getPathFromPackageName(config.getServiceImplPackage()));
        PATH_CONTROLLER_IMPL = getFilePath(saveDir, getPathFromPackageName(config.getControllerPackage()));

        /**
         * ??
         */
        FILE_OVERRIDE = config.isFileOverride();

        /**
         * ??
         */
        new AutoGenerator(config).generate();

        /**
         * ?
         * <p>
         * ? osName 
         * </p>
         */
        try {
            String osName = System.getProperty("os.name");
            if (osName != null) {
                if (osName.contains("Mac")) {
                    Runtime.getRuntime().exec("open " + config.getSaveDir());
                } else if (osName.contains("Windows")) {
                    Runtime.getRuntime().exec("cmd /c start " + config.getSaveDir());
                } else {
                    System.err.println("save dir:" + config.getSaveDir());
                }
            }
            System.out.println(" generate success! ");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ?????
     *
     * @param packageName
     * @return
     */
    protected static String getPathFromPackageName(String packageName) {
        if (StringUtils.isEmpty(packageName)) {
            return "";
        }
        return packageName.replace(".", File.separator);
    }

    /**
     * ??
     *
     * @param segment
     *            ?
     * @return
     */
    protected static String getFilePath(String savePath, String segment) {
        File folder = new File(savePath + File.separator + segment);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        return folder.getPath();
    }

    /**
     * ?
     */
    public void generate() {
        Connection conn = null;
        try {
            /**
             * 
             */
            Class.forName(config.getDbDriverName());
            conn = DriverManager.getConnection(config.getDbUrl(), config.getDbUser(), config.getDbPassword());

            /**
             * ???
             */
            boolean isOracle = false;
            if (config.getConfigDataSource() == ConfigDataSource.ORACLE) {
                isOracle = true;
            }

            /**
             * ?????
             */
            List<String> tables = getTables(conn);
            if (null == tables) {
                return;
            }

            Map<String, String> tableComments = getTableComment(conn);
            for (String table : tables) {
                List<String> columns = new ArrayList<String>();
                List<String> types = new ArrayList<String>();
                List<String> comments = new ArrayList<String>();
                /* ID ?,??? */
                boolean idExist = false;
                Map<String, IdInfo> idMap = new HashMap<String, IdInfo>();
                String tableFieldsSql = String.format(config.getConfigDataSource().getTableFieldsSql(), table);
                ResultSet results = conn.prepareStatement(tableFieldsSql).executeQuery();
                while (results.next()) {
                    String field = results.getString(config.getConfigDataSource().getFieldName());

                    /* ? baseEntity  */
                    if (null != config.getConfigBaseEntity()
                            && config.getConfigBaseEntity().includeColumns(field)) {
                        continue;
                    }

                    columns.add(field);
                    types.add(results.getString(config.getConfigDataSource().getFieldType()));
                    comments.add(results.getString(config.getConfigDataSource().getFieldComment()));
                    if (!isOracle && !idExist) {
                        /* MYSQL ID ?? */
                        String key = results.getString(config.getConfigDataSource().getFieldKey());
                        if ("PRI".equals(key)) {
                            boolean autoIncrement = false;
                            if ("auto_increment".equals(results.getString("EXTRA"))) {
                                autoIncrement = true;
                            }
                            idExist = true;
                            idMap.put(field, new IdInfo(field, autoIncrement));
                        }
                    }
                }
                if (isOracle) {
                    /* ORACLE ID ?? */
                    String idSql = String.format(
                            "SELECT A.COLUMN_NAME FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND B.CONSTRAINT_TYPE = 'P' AND A.TABLE_NAME = '%s'",
                            table);
                    ResultSet rs = conn.prepareStatement(idSql).executeQuery();
                    while (rs.next() && !idExist) {
                        String field = rs.getString(config.getConfigDataSource().getFieldKey());
                        idExist = true;
                        idMap.put(field, new IdInfo(field, false));
                    }
                }
                String beanName = getBeanName(table, config.isDbPrefix());
                String mapperName = String.format(config.getMapperName(), beanName);
                String mapperXMLName = String.format(config.getMapperXMLName(), beanName);
                String serviceName = String.format(config.getServiceName(), beanName);
                String serviceImplName = String.format(config.getServiceImplName(), beanName);
                String controllerName = String.format(config.getControllerName(), beanName);

                /**
                 * ???
                 */
                if (valideFile(PATH_ENTITY, beanName, JAVA_SUFFIX)) {
                    buildEntityBean(columns, types, comments, tableComments.get(table), idMap, table, beanName);
                }
                if (valideFile(PATH_MAPPER, mapperName, JAVA_SUFFIX)) {
                    buildMapper(beanName, mapperName);
                }
                if (valideFile(PATH_XML, mapperXMLName, XML_SUFFIX)) {
                    buildMapperXml(beanName, columns, types, comments, idMap, mapperName, mapperXMLName);
                }
                if (valideFile(PATH_SERVICE, serviceName, JAVA_SUFFIX)) {
                    buildService(beanName, serviceName);
                }
                if (valideFile(PATH_SERVICE_IMPL, serviceImplName, JAVA_SUFFIX)) {
                    buildServiceImpl(beanName, serviceImplName, serviceName, mapperName);
                }
                if (valideFile(PATH_CONTROLLER_IMPL, controllerName, JAVA_SUFFIX)) {
                    buildController(beanName, controllerName);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * ????
     *
     * @param dirPath
     * @param beanName
     * @param suffix
     * @return
     */
    protected boolean valideFile(String dirPath, String beanName, String suffix) {
        File file = new File(dirPath, beanName + suffix);
        return !file.exists() || FILE_OVERRIDE;
    }

    /**
     * ??dbTables.
     * <ul>
     * <li>?</li>
     * <li>custTables.</li>
     * <li>????null</li>
     * </ul>
     *
     * @return
     * @throws SQLException
     */
    protected List<String> getTables(Connection conn) throws SQLException {
        List<String> tables = new ArrayList<String>();
        PreparedStatement pstate = conn.prepareStatement(config.getConfigDataSource().getTablesSql());
        ResultSet results = pstate.executeQuery();
        while (results.next()) {
            tables.add(results.getString(1));
        }

        String[] tableNames = config.getTableNames();
        if (null == tableNames || tableNames.length == 0) {
            return tables;
        }

        // ???
        List<String> custTables = Arrays.asList(tableNames);
        List<String> notExistTables = new ArrayList<String>();
        for (String tb : custTables) {
            if (!tables.contains(tb)) {
                notExistTables.add(tb);
            }
        }
        if (notExistTables.size() == 0) {
            return custTables;
        }
        // ????null
        System.err.println("tablename " + notExistTables.toString() + " is not exist!! ==> stop generate!!");
        return null;
    }

    /**
     * ? beanName
     *
     * @param table
     *            ??
     * @return beanName
     */
    protected String getBeanName(String table, boolean includePrefix) {
        StringBuilder sb = new StringBuilder();
        if (table.contains("_")) {
            String[] tables = table.split("_");
            int l = tables.length;
            int s = 0;
            if (includePrefix) {
                s = 1;
            }
            for (int i = s; i < l; i++) {
                String temp = tables[i].trim();
                sb.append(temp.substring(0, 1).toUpperCase()).append(temp.substring(1).toLowerCase());
            }
        } else {
            sb.append(table.substring(0, 1).toUpperCase()).append(table.substring(1).toLowerCase());
        }
        return sb.toString();
    }

    protected String processType(String type) {
        if (config.getConfigDataSource() == ConfigDataSource.ORACLE) {
            return oracleProcessType(type);
        }
        return mysqlProcessType(type);
    }

    /**
     * MYSQL?
     *
     * @param type
     *            
     * @return
     */
    protected String mysqlProcessType(String type) {
        String t = type.toLowerCase();
        if (t.contains("char") || t.contains("text")) {
            return "String";
        } else if (t.contains("bigint")) {
            return "Long";
        } else if (t.contains("int")) {
            return "Integer";
        } else if (t.contains("date") || t.contains("time") || t.contains("year")) {
            return "Date";
        } else if (t.contains("text")) {
            return "String";
        } else if (t.contains("bit")) {
            return "Boolean";
        } else if (t.contains("decimal")) {
            return "BigDecimal";
        } else if (t.contains("blob")) {
            return "byte[]";
        } else if (t.contains("float")) {
            return "Float";
        } else if (t.contains("double")) {
            return "Double";
        } else if (t.contains("json") || t.contains("enum")) {
            return "String";
        }
        return null;
    }

    /**
     * ORACLE?
     *
     * @param type
     *            
     * @return
     */
    protected String oracleProcessType(String type) {
        String t = type.toUpperCase();
        if (t.contains("CHAR")) {
            return "String";
        } else if (t.contains("DATE") || t.contains("TIMESTAMP")) {
            return "Date";
        } else if (t.contains("NUMBER")) {
            if (t.matches("NUMBER\\(+\\d{1}+\\)")) {
                return "Integer";
            } else if (t.matches("NUMBER\\(+\\d{2}+\\)")) {
                return "Long";
            }
            return "Double";
        } else if (t.contains("FLOAT")) {
            return "Float";
        } else if (t.contains("BLOB")) {
            return "Object";
        } else if (t.contains("RAW")) {
            return "byte[]";
        }
        return null;
    }

    /**
     * ?
     *
     * @param types
     *            
     * @return
     */
    protected boolean isDate(List<String> types) {
        for (String type : types) {
            String t = type.toLowerCase();
            if (t.contains("date") || t.contains("time")) {
                return true;
            }
        }
        return false;
    }

    /**
     * ?
     *
     * @param types
     *            
     * @return
     */
    protected boolean isDecimal(List<String> types) {
        for (String type : types) {
            if (type.toLowerCase().contains("decimal")) {
                return true;
            }
        }
        return false;
    }

    /**
     * ?
     *
     * @param field
     *            
     * @return
     */
    protected String processField(String field) {
        /*
         * ??
         */
        if (!field.contains("_")) {
            if (StringUtils.isUpperCase(field)) {
                /*
                 * ???
                 */
                return field.toLowerCase();
            }
            return field;
        }

        /*
         * ???
         */
        StringBuilder sb = new StringBuilder();
        String[] fields = field.split("_");
        sb.append(fields[0].toLowerCase());
        for (int i = 1; i < fields.length; i++) {
            String temp = fields[i];
            sb.append(temp.substring(0, 1).toUpperCase());
            sb.append(temp.substring(1).toLowerCase());
        }
        return sb.toString();
    }

    /**
     * ?
     *
     * @param bw
     * @param text
     * @return
     * @throws IOException
     */
    protected BufferedWriter buildClassComment(BufferedWriter bw, String text) throws IOException {
        bw.newLine();
        bw.write("/**");
        bw.newLine();
        bw.write(" *");
        bw.newLine();
        bw.write(" * " + text);
        bw.newLine();
        bw.write(" *");
        bw.newLine();
        bw.write(" */");
        return bw;
    }

    /**
     * ?
     *
     * @param columns
     * @param types
     * @param comments
     * @throws IOException
     */
    protected void buildEntityBean(List<String> columns, List<String> types, List<String> comments,
            String tableComment, Map<String, IdInfo> idMap, String table, String beanName) throws IOException {
        File beanFile = new File(PATH_ENTITY, beanName + ".java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(beanFile)));
        bw.write("package " + config.getEntityPackage() + ";");
        bw.newLine();
        bw.newLine();
        bw.write("import java.io.Serializable;");
        bw.newLine();
        if (isDate(types)) {
            bw.write("import java.util.Date;");
            bw.newLine();
        }
        if (isDecimal(types)) {
            bw.write("import java.math.BigDecimal;");
            bw.newLine();
        }
        bw.newLine();
        if (config.getIdType() != IdType.ID_WORKER) {
            bw.write("import com.baomidou.mybatisplus.annotations.IdType;");
            bw.newLine();
        }
        bw.newLine();
        /*
         * ? BaseEntity 
         */
        if (null != config.getConfigBaseEntity() && null != config.getConfigBaseEntity().getPackageName()
                && !config.getEntityPackage().equals(config.getConfigBaseEntity().getPackageName())) {
            bw.write("import " + config.getConfigBaseEntity().getPackageName() + ";");
            bw.newLine();
        }
        bw.write("import com.baomidou.mybatisplus.annotations.TableField;");
        bw.newLine();
        if (null == config.getConfigBaseEntity()) {
            bw.write("import com.baomidou.mybatisplus.annotations.TableId;");
            bw.newLine();
        }
        if (table.contains("_") || config.isResultMap()) {
            bw.write("import com.baomidou.mybatisplus.annotations.TableName;");
            bw.newLine();
        }
        bw = buildClassComment(bw, tableComment);
        bw.newLine();
        /* ? */
        if (table.contains("_") || config.isResultMap()) {
            bw.write("@TableName(value=\"" + table + "\"");
            if (config.isResultMap()) {
                bw.write(",resultMap=\"BaseResultMap\"");
            }
            bw.write(")");
            bw.newLine();
        }

        /**
         * ???? BaseEntity 
         */
        if (null != config.getConfigBaseEntity()) {
            bw.write("public class " + beanName + " extends " + config.getConfigBaseEntity().getClassName() + " {");
        } else {
            bw.write("public class " + beanName + " implements Serializable {");
        }
        bw.newLine();
        bw.newLine();
        bw.write("\t@TableField(exist = false)");
        bw.newLine();
        bw.write("\tprivate static final long serialVersionUID = 1L;");
        bw.newLine();
        int size = columns.size();
        for (int i = 0; i < size; i++) {
            bw.newLine();
            bw.write("\t/** " + comments.get(i) + " */");
            bw.newLine();
            /*
             * ID  <br> isLine ??
             */
            String column = columns.get(i);
            String field = processField(column);
            boolean isLine = column.contains("_");
            IdInfo idInfo = idMap.get(column);
            if (idInfo != null) {
                // @TableId(value = "test_id", type = IdType.AUTO)
                bw.write("\t@TableId");
                String idType = toIdType();
                if (isLine) {
                    if (config.isDbColumnUnderline()) {
                        // 
                        if (null != idType) {
                            bw.write("(");
                            bw.write(idType);
                            bw.write(")");
                        }
                    } else {
                        bw.write("(value = \"" + column + "\"");
                        if (null != idType) {
                            bw.write(", ");
                            bw.write(idType);
                        }
                        bw.write(")");
                    }
                } else if (null != idType) {
                    bw.write("(");
                    bw.write(idType);
                    bw.write(")");
                }
                bw.newLine();
            } else if (isLine && !config.isDbColumnUnderline()) {
                // @TableField(value = "test_type", exist = false)
                bw.write("\t@TableField(value = \"" + column + "\")");
                bw.newLine();
            }
            bw.write("\tprivate " + processType(types.get(i)) + " " + field + ";");
            bw.newLine();
        }

        /*
         * ??
         */
        this.buildEntityBeanColumnConstant(columns, types, comments, bw, size);
        bw.newLine();

        /*
         * ?get  set
         */
        for (int i = 0; i < size; i++) {
            String _tempType = processType(types.get(i));
            String _tempField = processField(columns.get(i));
            String _field = _tempField.substring(0, 1).toUpperCase() + _tempField.substring(1);
            bw.newLine();
            bw.write("\tpublic " + _tempType + " get" + _field + "() {");
            bw.newLine();
            bw.write("\t\treturn this." + _tempField + ";");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            /* ? */
            if (config.isBuliderModel()) {
                bw.write("\tpublic " + beanName + " set" + _field + "(" + _tempType + " " + _tempField + ") {");
                bw.newLine();
                bw.write("\t\tthis." + _tempField + " = " + _tempField + ";");
                bw.newLine();
                bw.write("\t\treturn this;");
            } else {
                bw.write("\tpublic void set" + _field + "(" + _tempType + " " + _tempField + ") {");
                bw.newLine();
                bw.write("\t\tthis." + _tempField + " = " + _tempField + ";");
            }
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
        }

        bw.newLine();
        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
    }

    protected void buildEntityBeanColumnConstant(List<String> columns, List<String> types, List<String> comments,
            BufferedWriter bw, int size) throws IOException {
        /*
         * ???? false
         */
        if (config.isColumnConstant()) {
            for (int i = 0; i < size; i++) {
                String _tempType = processType(types.get(i));
                String _column = columns.get(i);
                bw.newLine();
                bw.write("\tpublic static final " + _tempType + " " + _column.toUpperCase() + " = \"" + _column
                        + "\";");
            }
            bw.newLine();
        }
    }

    public String toIdType() {
        if (config.getIdType() == IdType.AUTO) {
            return "type = IdType.AUTO";
        } else if (config.getIdType() == IdType.INPUT) {
            return "type = IdType.INPUT";
        } else if (config.getIdType() == IdType.UUID) {
            return "type = IdType.UUID";
        }
        return null;
    }

    /**
     * Mapper
     *
     * @param beanName
     * @param mapperName
     * @throws IOException
     */
    protected void buildMapper(String beanName, String mapperName) throws IOException {
        File mapperFile = new File(PATH_MAPPER, mapperName + ".java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapperFile), "utf-8"));
        bw.write("package " + config.getMapperPackage() + ";");
        bw.newLine();
        bw.newLine();
        bw.write("import " + config.getEntityPackage() + "." + beanName + ";");
        bw.newLine();
        bw.write("import com.baomidou.mybatisplus.mapper.BaseMapper;");
        bw.newLine();

        bw = buildClassComment(bw, beanName + " ??");
        bw.newLine();
        bw.write("public interface " + mapperName + " extends BaseMapper<" + beanName + "> {");
        bw.newLine();
        bw.newLine();

        // ----------mapperEnd----------
        bw.newLine();
        bw.write("}");
        bw.flush();
        bw.close();
    }

    /**
     * XML
     *
     * @param beanName
     * @param columns
     * @param types
     * @param comments
     * @throws IOException
     */
    protected void buildMapperXml(String beanName, List<String> columns, List<String> types, List<String> comments,
            Map<String, IdInfo> idMap, String mapperName, String mapperXMLName) throws IOException {
        File mapperXmlFile = new File(PATH_XML, mapperXMLName + ".xml");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapperXmlFile)));
        bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        bw.newLine();
        bw.write(
                "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">");
        bw.newLine();
        bw.write("<mapper namespace=\"" + config.getMapperPackage() + "." + mapperName + "\">");
        bw.newLine();
        bw.newLine();

        /*
         * ?SqlMapper
         */
        if (config.isResultMap()) {
            buildResultMap(bw, beanName, idMap, columns);
        } else {
            buildSQL(bw, idMap, columns);
        }

        bw.write("</mapper>");
        bw.flush();
        bw.close();
    }

    /**
     * service
     *
     * @param beanName
     * @param serviceName
     * @throws IOException
     */
    protected void buildService(String beanName, String serviceName) throws IOException {
        File serviceFile = new File(PATH_SERVICE, serviceName + ".java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(serviceFile), "utf-8"));
        bw.write("package " + config.getServicePackage() + ";");
        bw.newLine();
        bw.newLine();
        bw.write("import " + config.getEntityPackage() + "." + beanName + ";");
        bw.newLine();
        String superService = config.getSuperService();
        bw.write("import " + superService + ";");
        bw.newLine();

        bw = buildClassComment(bw, beanName + " ???");
        bw.newLine();
        superService = superService.substring(superService.lastIndexOf(".") + 1);
        bw.write("public interface " + serviceName + " extends " + superService + "<" + beanName + "> {");
        bw.newLine();
        bw.newLine();

        // ----------serviceEnd----------
        bw.newLine();
        bw.write("}");
        bw.flush();
        bw.close();
    }

    /**
     * service
     *
     * @param beanName
     * @param serviceImplName
     * @param mapperName
     * @throws IOException
     */
    protected void buildServiceImpl(String beanName, String serviceImplName, String serviceName, String mapperName)
            throws IOException {
        File serviceFile = new File(PATH_SERVICE_IMPL, serviceImplName + ".java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(serviceFile), "utf-8"));
        bw.write("package " + config.getServiceImplPackage() + ";");
        bw.newLine();
        bw.newLine();
        bw.write("import org.springframework.stereotype.Service;");
        bw.newLine();
        bw.newLine();
        bw.write("import " + config.getMapperPackage() + "." + mapperName + ";");
        bw.newLine();
        bw.write("import " + config.getEntityPackage() + "." + beanName + ";");
        bw.newLine();
        bw.write("import " + config.getServicePackage() + "." + serviceName + ";");
        bw.newLine();

        String superServiceImpl = config.getSuperServiceImpl();
        bw.write("import " + superServiceImpl + ";");
        bw.newLine();

        bw = buildClassComment(bw, beanName + " ???");
        bw.newLine();
        bw.write("@Service");
        bw.newLine();
        superServiceImpl = superServiceImpl.substring(superServiceImpl.lastIndexOf(".") + 1);
        bw.write("public class " + serviceImplName + " extends " + superServiceImpl + "<" + mapperName + ", "
                + beanName + "> implements " + serviceName + " {");
        bw.newLine();
        bw.newLine();

        // ----------serviceEnd----------
        bw.newLine();
        bw.write("}");
        bw.flush();
        bw.close();
    }

    /**
     * Controller
     *
     * @param beanName
     * @param controllerName
     * @throws IOException
     */
    protected void buildController(String beanName, String controllerName) throws IOException {
        File serviceFile = new File(PATH_CONTROLLER_IMPL, controllerName + ".java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(serviceFile), "utf-8"));
        bw.write("package " + config.getControllerPackage() + ";");
        bw.newLine();
        bw.newLine();
        bw.write("import org.springframework.stereotype.Controller;");
        bw.newLine();

        bw = buildClassComment(bw, beanName + " ");
        bw.newLine();
        bw.write("@Controller");
        bw.newLine();
        bw.write("public class " + controllerName + " {");
        bw.newLine();
        bw.newLine();
        bw.newLine();
        bw.write("}");
        bw.flush();
        bw.close();
    }

    /**
     * ?
     *
     * @param bw
     * @param idMap
     * @param columns
     * @throws IOException
     */
    protected void buildSQL(BufferedWriter bw, Map<String, IdInfo> idMap, List<String> columns) throws IOException {
        int size = columns.size();
        bw.write("\t<!-- -->");
        bw.newLine();
        bw.write("\t<sql id=\"Base_Column_List\">");
        bw.newLine();
        bw.write("\t\t");

        /*
         * ?
         */
        DBType dbType = DBType.ORACLE;
        if (config.getConfigDataSource() == ConfigDataSource.MYSQL) {
            dbType = DBType.MYSQL;
        }

        /*
         * 
         */
        if (null != config.getConfigBaseEntity()) {
            for (String column : config.getConfigBaseEntity().getColumns()) {
                bw.write(SqlReservedWords.convert(dbType, column));
                if (column.contains("_")) {
                    bw.write(" AS " + processField(column));
                }
                bw.write(", ");
            }
        }
        /**
         * 
         */
        for (int i = 0; i < size; i++) {
            String column = columns.get(i);
            IdInfo idInfo = idMap.get(column);
            if (idInfo != null) {
                bw.write(SqlReservedWords.convert(dbType, column));
                if (idInfo.getValue().contains("_")) {
                    bw.write(" AS " + processField(idInfo.getValue()));
                }
            } else {
                if (null == config.getConfigBaseEntity()) {
                    bw.write(" ");
                }
                bw.write(SqlReservedWords.convert(dbType, column));
                if (column.contains("_")) {
                    bw.write(" AS " + processField(column));
                }
            }
            if (i != size - 1) {
                bw.write(",");
            }
        }
        bw.newLine();
        bw.write("\t</sql>");
        bw.newLine();
        bw.newLine();
    }

    /**
     *  ResultMap ?
     *
     * @param bw
     * @param beanName
     * @param idMap
     * @param columns
     * @throws IOException
     */
    protected void buildResultMap(BufferedWriter bw, String beanName, Map<String, IdInfo> idMap,
            List<String> columns) throws IOException {
        int size = columns.size();
        bw.write("\t<!-- -->");
        bw.newLine();
        bw.write("\t<resultMap id=\"BaseResultMap\" type=\"" + config.getEntityPackage() + "." + beanName + "\">");
        bw.newLine();

        /*
         * ?
         */
        DBType dbType = DBType.ORACLE;
        if (config.getConfigDataSource() == ConfigDataSource.MYSQL) {
            dbType = DBType.MYSQL;
        }

        /*
         * 
         */
        if (null != config.getConfigBaseEntity()) {
            for (String column : config.getConfigBaseEntity().getColumns()) {
                bw.write("\t\t<result column=\"" + SqlReservedWords.convert(dbType, column) + "\" property=\""
                        + processField(column) + "\" />");
                bw.newLine();
            }
        }
        /**
         * 
         */
        for (int i = 0; i < size; i++) {
            String column = columns.get(i);
            IdInfo idInfo = idMap.get(column);
            if (idInfo != null) {
                bw.write("\t\t<id column=\"" + SqlReservedWords.convert(dbType, column) + "\" property=\""
                        + processField(idInfo.getValue()) + "\" />");
            } else {
                if (null == config.getConfigBaseEntity()) {
                    bw.write(" ");
                }
                bw.write("\t\t<result column=\"" + SqlReservedWords.convert(dbType, column) + "\" property=\""
                        + processField(column) + "\" />");
            }
            if (i != size - 1) {
                bw.newLine();
            }
        }
        bw.newLine();
        bw.write("\t</resultMap>");
        bw.newLine();
        bw.newLine();
    }

    /**
     * ??
     *
     * @return
     * @throws SQLException
     */
    protected Map<String, String> getTableComment(Connection conn) throws SQLException {
        Map<String, String> maps = new HashMap<String, String>();
        PreparedStatement pstate = conn.prepareStatement(config.getConfigDataSource().getTableCommentsSql());
        ResultSet results = pstate.executeQuery();
        while (results.next()) {
            maps.put(results.getString(config.getConfigDataSource().getTableName()),
                    results.getString(config.getConfigDataSource().getTableComment()));
        }
        return maps;
    }

    class IdInfo {
        private String value;
        private boolean autoIncrement;

        public IdInfo(String value, boolean autoIncrement) {
            this.value = value;
            this.autoIncrement = autoIncrement;

        }

        public String getValue() {
            return value;
        }

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

        public boolean isAutoIncrement() {
            return autoIncrement;
        }

        public void setAutoIncrement(boolean autoIncrement) {
            this.autoIncrement = autoIncrement;
        }
    }
}