基于FreeMarker和DBUtils的代码生成器

相关博客

基于FreeMarker和DBUtils的JavaWeb代码生成器 一基于FreeMarker和DBUtils的JavaWeb代码生成器 二基于FreeMarker和DBUtils的JavaWeb代码生成器 三 源代码下载地址:DBUtilsGenerator

项目说明

本代码生成器的功能是:采用FreeMarker技术的生成基础DBUtils的JavaWeb项目代码。
本项目是我在2017年12月份,利用业余时间写了大概4、5天的时间,利用该生成器能够生成JavaWeb项目后台代码50%左右的工作量。
使用本代码生成器,只需要先按照下面的数据库设计规范设计好数据库,然后使用代码生成器就能一键生成项目代码,生成的代码有:实体类、DAO接口及实现类、Service接口及实现类、Controller代码框架。

本代码生成器要求数据库设计遵循以下规范

  • 数据库命名:db_具体数据库名
  • 表命名:tb_具体表名
  • 符合驼峰式命名

代码生成器的目录结构如下:

wsdl自动生成java代码 java web代码生成器_sql

具体实现

1、用来封装数据库表结构的实体类:Item.java

public class Item {
	private String propertyName;// 实体类成员变量名
	private String javaType;// 实体类成员变量类型

	private String fieldName;// 表字段名
	private String comment;
	private String sqlType;// 表字段类型

	private boolean pk;// 是否是主键

	public Item() {
	}

	public Item(String javaType, String propertyName) {
		this.propertyName = propertyName;
		this.javaType = javaType;
	}

	

	public Item(String javaType, String propertyName, String comment) {
		super();
		this.javaType = javaType;
		this.propertyName = propertyName;
		this.comment = comment;
	}

	public Item(String propertyName, String comment, String javaType, String fieldName, String sqlType) {
		this.propertyName = propertyName;
		this.comment = comment;
		this.javaType = javaType;
		this.fieldName = fieldName;
		this.sqlType = sqlType;
	}

	public Item(String propertyName, String javaType, String fieldName, String sqlType, boolean pk) {
		this.propertyName = propertyName;
		this.javaType = javaType;
		this.fieldName = fieldName;
		this.sqlType = sqlType;
		this.pk = pk;
	}

	public boolean isPk() {
		return pk;
	}

	public void setPk(boolean pk) {
		this.pk = pk;
	}

	public String getComment() {
		return comment;
	}

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

	public String getJavaType() {
		return javaType;
	}

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

	public String getSqlType() {
		return sqlType;
	}

	public void setSqlType(String sqlType) {
		this.sqlType = sqlType;
	}

	public String getFieldName() {
		return fieldName;
	}

	public void setFieldName(String fieldName) {
		this.fieldName = fieldName;
	}

	public String getPropertyName() {
		return propertyName;
	}

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

	@Override
	public String toString() {
		return "Item{" + "propertyName='" + propertyName + '\'' + ", javaType='" + javaType + '\'' + ", fieldName='"
				+ fieldName + '\'' + ", sqlType='" + sqlType + '\'' + ", pk=" + pk + '}';
	}
}

2、操作数据库的工具类:DBUtils.java

public class DBUtils {

	// 数据库连接信息
	protected final String URL_PREFIX = "jdbc:mysql://localhost:3306/";
	protected static String driver = "com.mysql.cj.jdbc.Driver";
	protected String url;
	protected String username;
	protected String password;

	public DBUtils() {
	}

	static {// 读取配置文件,初始化数据
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public Connection getConnection() throws SQLException {
		return DriverManager.getConnection(url, username, password);
	}

	public Connection getConnection(String url) throws ClassNotFoundException, SQLException {
		return DriverManager.getConnection(url, username, password);
	}

	public void closeAll(Connection conn, Statement stmt, ResultSet rs) {
		try { // 建议采用这种形式来释放资源,因为finally里面的一定会被释放
			if (rs != null) {
				rs.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				if (conn != null) {
					try {
						conn.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	// 内部数据格式:表名 <对应Java类型 修正后的表字段名 对应Java类型 修正后的表字段名。。。>
	protected static Map<String, List<Item>> tableInfoList = new HashMap<>();// tb_dept <java.lang.Integer deptno>

	protected void readTableMetaData(String databaseName) throws Exception {
		List<String> tables = getAllTableNamesByDatabase(databaseName);

		// 遍历每一个表取出表中字段的名称、类型、对应的Java类型等信息
		for (String table : tables) {// 遍历每一个表取出表中字段的名称、类型、对应的Java类型等信息
			Connection conn = null;
			Statement stmt = null;
			ResultSet rs = null;

			try {
				conn = getConnection();
				stmt = conn.createStatement();
				rs = stmt.executeQuery("show full columns from " + table);// 得到表的描述信息(字段名称、数据类型等)

				List<Item> paramList = new ArrayList<>();
				while (rs.next()) {
					String fieldName = rs.getString("field");
					String propertyName = Tools.field2Property(fieldName);

					String comment = rs.getString("Comment");

					String sqlType = rs.getString("type").toUpperCase();
					String javaType = getJavaTypeByDbType(sqlType);
					if (sqlType.contains("(")) {
						sqlType = sqlType.substring(0, sqlType.indexOf("("));
					}

					if (sqlType.equals("INT")) {// MyBatis中JdbcType的int类型的名称为INTEGER
						sqlType = "INTEGER";
					}
					Item item = new Item(propertyName, comment, javaType, fieldName, sqlType);

					if (getPK(table).size() > 0 && getPK(table).get(0).equalsIgnoreCase(fieldName)) {
						item.setPk(true);
					}

					paramList.add(item);
				}
				tableInfoList.put(table, paramList);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				closeAll(conn, stmt, rs);
			}
		}

	}

	private List<String> getAllTableNamesByDatabase(String databaseName) {
		List<String> tables = new ArrayList<>();// 用来放置所有表的名字
		// 获取当前数据库所有的表名
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = getConnection();
			ps = conn.prepareStatement("select table_name from information_schema.TABLES where TABLE_SCHEMA=?");
			ps.setString(1, databaseName);
			rs = ps.executeQuery();
			while (rs.next()) {
				tables.add(rs.getString("TABLE_NAME"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			closeAll(conn, ps, rs);
		}
		return tables;
	}

	private String getJavaTypeByDbType(String type) {
		String javaType = null;
		if (type.indexOf("CHAR") > -1 || type.indexOf("TEXT") > -1 || type.indexOf("ENUM") > -1
				|| type.indexOf("SET") > -1) {
			javaType = "java.lang.String";
		} else if (type.indexOf("TIME") > -1 || type.indexOf("DATE") > -1 || type.indexOf("YEAR") > -1) {
			javaType = "java.util.Date";
		} else if (type.indexOf("BIGINT") > -1) {
			javaType = "java.lang.Long";
		} else if (type.indexOf("TINYINT") > -1) {
			javaType = "java.lang.Byte";
		} else if (type.indexOf("INT") > -1) {
			javaType = "java.lang.Integer";
		} else if (type.indexOf("BIT") > -1) {
			javaType = "java.lang.Boolean";
		} else if (type.indexOf("FLOAT") > -1 || type.indexOf("REAL") > -1) {
			javaType = "java.lang.Double";
		} else if (type.indexOf("DOUBLE") > -1 || type.indexOf("NUMERIC") > -1) {
			javaType = "java.lang.Double";
		} else if (type.indexOf("BLOB") > -1 || type.indexOf("BINARY") > -1) {
			javaType = "byte[]";
		} else if (type.indexOf("JSON") > -1) {
			javaType = "java.lang.String";
		} else if (type.indexOf("DECIMAL") > -1) {
			javaType = "java.math.BigDecimal";
		} else {
			System.out.println("type:" + type);
		}
		return javaType;
	}

	/**
	 * 返回数据表中的主键
	 *
	 * @param table
	 * @return
	 * @throws SQLException
	 */
	protected List<String> getPK(String table) throws SQLException {
		List<String> res = new ArrayList<>();
		Connection conn = getConnection();
		String catalog = conn.getCatalog(); // catalog 其实也就是数据库名
		DatabaseMetaData metaData = conn.getMetaData();

		ResultSet rs = null;
		rs = metaData.getPrimaryKeys(catalog, null, table);// 适用mysql
		while (rs.next()) {
			res.add(rs.getString("COLUMN_NAME"));
		}
		closeAll(conn, null, rs);
		return res;
	}

	/**
	 * 返回数据表中的外键
	 *
	 * @param table
	 * @return
	 * @throws SQLException
	 */
	protected List<String> getFk(String table) throws SQLException {
		List<String> res = new ArrayList<>();
		Connection conn = getConnection();
		String catalog = conn.getCatalog(); // catalog 其实也就是数据库名
		DatabaseMetaData metaData = conn.getMetaData();

		ResultSet rs = metaData.getImportedKeys(catalog, null, table);
		while (rs.next()) {
			res.add(rs.getString("FKCOLUMN_NAME"));
		}
		closeAll(conn, null, rs);
		return res;
	}

	protected Map<String, String> getFkNameType(String table) throws SQLException {
		Map<String, String> res = new HashMap<>();
		Connection conn = getConnection();
		String catalog = conn.getCatalog(); // catalog 其实也就是数据库名
		DatabaseMetaData metaData = conn.getMetaData();

		ResultSet rs = metaData.getImportedKeys(catalog, null, table);
		while (rs.next()) {
			String fkColumnName = rs.getString("FKCOLUMN_NAME");
			String fkName = null;
			int endIndex = fkColumnName.lastIndexOf('_');
			if (endIndex > 0) {
				fkName = fkColumnName.substring(0, endIndex);
			} else {
				fkName = fkColumnName;
			}

			String pkTablenName = rs.getString("PKTABLE_NAME");
			String fkType = Tools.getEntryName(pkTablenName);
			res.put(fkType, fkName);
		}
		closeAll(conn, null, rs);
		return res;
	}
}

3、删除文件或目录的工具类:DeleteFileUtil.java

public class DeleteFileUtil {

    /**
     * 删除文件,可以是文件或文件夹
     *
     * @param fileName
     *            要删除的文件名
     * @return 删除成功返回true,否则返回false
     */
    public static boolean delete(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            System.out.println("删除文件失败:" + fileName + "不存在!");
            return false;
        } else {
            if (file.isFile())
                return deleteFile(fileName);
            else
                return deleteDirectory(fileName);
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName
     *            要删除的文件的文件名
     * @return 单个文件删除成功返回true,否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                System.out.println("删除单个文件" + fileName + "成功!");
                return true;
            } else {
                System.out.println("删除单个文件" + fileName + "失败!");
                return false;
            }
        } else {
            System.out.println("删除单个文件失败:" + fileName + "不存在!");
            return false;
        }
    }

    /**
     * 删除目录及目录下的文件
     *
     * @param dir
     *            要删除的目录的文件路径
     * @return 目录删除成功返回true,否则返回false
     */
    public static boolean deleteDirectory(String dir) {
        // 如果dir不以文件分隔符结尾,自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        // 如果dir对应的文件不存在,或者不是一个目录,则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            System.out.println("删除目录失败:" + dir + "不存在!");
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                flag = DeleteFileUtil.deleteFile(files[i].getAbsolutePath());
                if (!flag)
                    break;
            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                flag = DeleteFileUtil.deleteDirectory(files[i]
                        .getAbsolutePath());
                if (!flag)
                    break;
            }
        }
        if (!flag) {
            System.out.println("删除目录失败!");
            return false;
        }
        // 删除当前目录
        if (dirFile.delete()) {
            System.out.println("删除目录" + dir + "成功!");
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
//  // 删除单个文件
//  String file = "c:/test/test.txt";
//  DeleteFileUtil.deleteFile(file);
//  System.out.println();
        // 删除一个目录
        String dir = "D:/abc";
        DeleteFileUtil.deleteDirectory(dir);
//  System.out.println();
//  // 删除文件
//  dir = "c:/test/test0";
//  DeleteFileUtil.delete(dir);

    }

}

4、项目工具类:Tools.java

public class Tools {
	// 首字母转小写
	public static String First2LowerCase(String s) {
		if (Character.isLowerCase(s.charAt(0))) {
			return s;
		} else {
			return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
		}
	}

	// 首字母转大写
	public static String First2UpperCase(String s) {
		if (Character.isUpperCase(s.charAt(0))) {
			return s;
		} else {
			return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
		}
	}

	// 将表字段名中的下划线_去掉
	public static String field2Property(String columnName) {
		while (columnName.indexOf("_") > -1) {
			int index = columnName.indexOf("_");
			columnName = columnName.substring(0, index)
					+ columnName.substring(index, index + 2).toUpperCase().substring(1)
					+ columnName.substring(index + 2, columnName.length());
		}
		return columnName;
	}

	/**
	 * 获取表名所对应的实体类的名称,默认每个表名都有一个前缀,将前缀给干掉
	 * 
	 * @param table
	 * @return
	 */
	public static String getEntryName(String table) {
		String tb = table.trim();
		String temp = Tools.First2UpperCase(tb.substring(tb.indexOf('_') + 1));
		return field2Property(temp);
	}

}

5、常量类:Constant.java

public interface Constant {
    //各模板文件的路径
    String entityFile = "genResources\\\\ftl\\\\entity.ftl";
    String daoFile = "genResources\\\\ftl\\\\dao.ftl";
    String daoImplFile = "genResources\\\\ftl\\\\daoImpl.ftl";
    String serviceFile = "genResources\\\\ftl\\\\service.ftl";
    String serviceImplFile = "genResources\\\\ftl\\\\serviceImpl.ftl";
    String controllerFile = "genResources\\\\ftl\\\\controller.ftl";
    String dbutilFile = "genResources\\\\ftl\\\\dbutil.ftl";
    String pageBeanFile = "genResources\\\\ftl\\\\pageBean.ftl";
    String pageParamFile = "genResources\\\\ftl\\\\pageParam.ftl";
    String constFile = "genResources\\\\ftl\\\\const.ftl";
    String druidFile = "genResources\\\\ftl\\\\druid.ftl";
}

6、代码生成器工具类:GenerateUtil.java

public class GenerateUtil extends DBUtils {

private String base = System.getProperty("user.dir") + "\\src";// user.dir得到的是项目的绝对路径

private String databaseName;

private String utils;
private String baseUrl;
private String controllerStr;
private String serviceStr;
private String entityStr;
private String implStr;
private String daoStr;

public GenerateUtil(String databaseName, String username, String password, String utils, String baseUrl,
		String controllerStr, String serviceStr, String entityStr, String implStr, String daoStr,
		String sourcePath) {
	this.databaseName = databaseName;
	this.username = username;
	this.password = password;

	url = URL_PREFIX + databaseName + "?useSSL=false&serverTimezone=UTC&user=root&password=&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&failOverReadOnly=false";

	this.utils = utils;
	this.baseUrl = baseUrl;
	this.controllerStr = controllerStr;
	this.serviceStr = serviceStr;
	this.entityStr = entityStr;
	this.implStr = implStr;
	this.implStr = implStr;
	this.daoStr = daoStr;

	if (sourcePath.length() > 0) {
		this.base = sourcePath;
	}
}

public void createClassByMySqlTable() throws Exception {
	System.out.println("generating....");

	readTableMetaData(databaseName);

	createPackage(); // 创建包

	createEntityFile(); // 创建实体类
	createDaoFile(); // 创建Dao接口
	createDaoImplFile(); // 创建Mapper映射文件

	createServiceFile();
	createServiceImplFile();

	createPageBeanFile();
	createPageParamFile();
	createConstFile();
	createDBUtilFile();

	createDBCPCfgFile();

	createControllerFile();
	
	System.out.println("generate success!");
}

private void createControllerFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型

	for (String table : tableInfoList.keySet()) {
		String newEntity = Tools.getEntryName(table);
		// 生成类所对应的package语句
		data.put("pkg", baseUrl.replace("main.java.", "") + "." + controllerStr);
		data.put("serviceNameWithPkg",
				baseUrl.replace("main.java.", "") + "." + serviceStr + "." + newEntity + "Service");
		data.put("serviceNameImplWithPkg", baseUrl.replace("main.java.", "") + "." + serviceStr + "." + implStr
				+ "." + newEntity + "ServiceImpl");
		data.put("clazzName", newEntity);

		String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + controllerStr + "\\" + newEntity
				+ "Controller.java";
		Writer out = new FileWriter(new File(fileName));
		FreemarkerUtil.execute(Constant.controllerFile, data, out);
	}
}

private void createPackage() {
	String[] baseUrls = baseUrl.split("[.]");
	String basePackage = base;
	File fileBase = new File(basePackage);
	if(fileBase.exists()) {
		DeleteFileUtil.deleteDirectory(basePackage);
	}
	
	for (String b : baseUrls) {
		basePackage += "\\" + b;
		File file = new File(basePackage);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	new File(basePackage + "\\" + entityStr).mkdir();
	new File(basePackage + "\\" + serviceStr).mkdir();
	new File(basePackage + "\\" + serviceStr + "\\" + implStr).mkdir();
	new File(basePackage + "\\" + controllerStr).mkdir();
	new File(basePackage + "\\" + daoStr).mkdir();
	new File(basePackage + "\\" + daoStr + "\\" + implStr).mkdir();
	new File(basePackage + "\\" + utils).mkdir();
}

private void createEntityFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型

	for (String table : tableInfoList.keySet()) {
		String newEntity = Tools.getEntryName(table);

		data.put("clazzName", newEntity);// 生成类所对应的package语句
		data.put("pkg", baseUrl.replace("main.java.", "") + "." + entityStr); // 生成Entity类

		Set<String> importList = new HashSet<>(); // 用来生成import语句
		List<Item> propertyList = new ArrayList<>(); // 用来生成各属性

		// 用来生成主键
		String pk = getPK(table).get(0);
		data.put("pk", Tools.field2Property(pk));

		List<Item> paramList = tableInfoList.get(table);
		for (Item item : paramList) {
			String javaType = item.getJavaType();
			String propertyName = item.getPropertyName();
			if (propertyName.equals(Tools.field2Property(pk))) {
				data.put("pkType", javaType);// 主键的数据类型
			}
			importList.add(javaType);
			propertyList.add(new Item(javaType.substring(javaType.lastIndexOf(".") + 1),
					Tools.field2Property(propertyName), item.getComment()));
		}

		Map<String, String> fkNameTypeList = getFkNameType(table);
		data.put("fkNameTypeList", fkNameTypeList);

		data.put("importList", importList);
		data.put("propertyList", propertyList);

		String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + entityStr + "\\" + newEntity + ".java";
		Writer out = new FileWriter(new File(fileName));
		FreemarkerUtil.execute(Constant.entityFile, data, out);
	}

}

private void createDaoFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型

	for (String table : tableInfoList.keySet()) {
		String newEntity = Tools.getEntryName(table);
		// 生成类所对应的package语句
		data.put("clazzNameWithPkg", baseUrl.replace("main.java.", "") + "." + entityStr + "." + newEntity);
		data.put("clazzName", newEntity);
		data.put("pkg", baseUrl.replace("main.java.", "") + "." + daoStr);
		data.put("pageParamWithPkg", baseUrl.replace("main.java.", "") + "." + utils + "." + "PageParam");
		
		// 获取主键
		String pk = getPK(table).get(0);
		data.put("pk", Tools.field2Property(pk));

		// 获取外键
		List<String> fks = getFk(table);
		List<Item> fkItemList = new ArrayList<>();

		List<Item> paramList = tableInfoList.get(table);
		for (Item item : paramList) {
			String javaType = item.getJavaType();
			String propertyName = item.getPropertyName();
			if (propertyName.equals(Tools.field2Property(pk))) {
				data.put("pkType", javaType.substring(javaType.lastIndexOf(".") + 1));// 主键的数据类型
			}

			if (fks.contains(item.getFieldName())) {
				fkItemList.add(item);
			}

		}

		data.put("fkItemList", fkItemList);

		String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + daoStr + "\\" + newEntity + "Dao.java";
		Writer out = new FileWriter(new File(fileName));
		FreemarkerUtil.execute(Constant.daoFile, data, out);
	}
}

private void createDaoImplFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型

	for (String table : tableInfoList.keySet()) {
		String newEntity = Tools.getEntryName(table);
		// 生成类所对应的package语句
		data.put("clazzNameWithPkg", baseUrl.replace("main.java.", "") + "." + entityStr + "." + newEntity);
		data.put("clazzName", newEntity);
		String pkg = baseUrl.replace("main.java.", "") + "." + daoStr + "." + implStr;
		data.put("pkg", pkg);
		data.put("daoNameWithPkg", baseUrl.replace("main.java.", "") + "." + daoStr + "." + newEntity + "Dao");
		data.put("dbutil", baseUrl.replace("main.java.", "") + "." + utils + "." + "DBUtil");
		data.put("pageParamWithPkg", baseUrl.replace("main.java.", "") + "." + utils + "." + "PageParam");
		data.put("tableName", table);
		
		// 生成主键
		String pk = getPK(table).get(0);
		data.put("pkColumnName", pk);
		data.put("pk", Tools.field2Property(pk));
		// 获取外键
		List<String> fks = getFk(table);
		List<Item> fkItemList = new ArrayList<>();

		StringBuilder fieldList = new StringBuilder("(");
		StringBuilder wenHaoList = new StringBuilder("(");
		StringBuilder propertyList = new StringBuilder();

		StringBuilder updateList = new StringBuilder();
		StringBuilder updateValueList = new StringBuilder();

		String newEntityObj = Tools.First2LowerCase(newEntity);

		String searchFields = "";

		StringBuffer updateYuJu = new StringBuffer();
		
		List<Item> propList = new ArrayList<>();
		List<Item> paramList = tableInfoList.get(table);
		for (Item item : paramList) {
			fieldList.append(item.getFieldName()).append(", ");
			wenHaoList.append("?, ");
			propertyList.append(newEntityObj).append(".get").append(Tools.First2UpperCase(item.getPropertyName()))
					.append("()").append(", ");

			updateYuJu.append("\t\tif(").append(newEntityObj).append(".get")
					.append(Tools.First2UpperCase(item.getPropertyName())).append("() != null){");
			updateYuJu.append("\n\t\t\tparamBuf.append(\" " + item.getFieldName() + "= ? and\");");
			updateYuJu.append("\n\t\t\tparamValueList.add(" + newEntityObj + ".get"
					+ Tools.First2UpperCase(item.getPropertyName()) + "());");
			updateYuJu.append("\n\t\t}\n");

			String javaType = item.getJavaType();
			String propertyName = item.getPropertyName();
			if (propertyName.equals(Tools.field2Property(pk))) {
				data.put("pkType", javaType.substring(javaType.lastIndexOf(".") + 1));// 主键的数据类型
			} else {
				updateList.append(item.getFieldName()).append("= ? ,");
				updateValueList.append(newEntityObj).append(".get")
						.append(Tools.First2UpperCase(item.getPropertyName())).append("()").append(", ");
			}

			if (fks.contains(item.getFieldName())) {
				fkItemList.add(item);
			}
			searchFields += item.getFieldName() + " as " + item.getPropertyName() + ", ";
			propList.add(new Item(javaType.substring(javaType.lastIndexOf(".") + 1),
					Tools.field2Property(propertyName), item.getComment()));
		}

		data.put("updateYuJu", updateYuJu);
		
		data.put("searchFields", searchFields.substring(0, searchFields.length() - 2));
		data.put("fkItemList", fkItemList);

		String fieldStr = fieldList.substring(0, fieldList.length() - 2).concat(")");
		data.put("fieldStr", fieldStr);
		String wenHaoStr = wenHaoList.substring(0, wenHaoList.length() - 2).concat(")");
		data.put("wenHaoStr", wenHaoStr);
		String valueStr = propertyList.substring(0, propertyList.length() - 2);
		data.put("valueStr", valueStr);

		String updateStr = updateList.substring(0, updateList.length() - 2);
		data.put("updateStr", updateStr);
		updateValueList.append(newEntityObj).append(".get").append(Tools.First2UpperCase(Tools.field2Property(pk))).append("()");
		data.put("updateValueStr", updateValueList.toString());

		data.put("propertyList", propList);
		
		String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + daoStr + "\\" + implStr + "\\"
				+ newEntity + "DaoImpl.java";
		Writer out = new FileWriter(new File(fileName));
		FreemarkerUtil.execute(Constant.daoImplFile, data, out);
	}
}

private void createServiceFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型

	for (String table : tableInfoList.keySet()) {
		String newEntity = Tools.getEntryName(table);
		// 生成类所对应的package语句
		data.put("clazzNameWithPkg", baseUrl.replace("main.java.", "") + "." + entityStr + "." + newEntity);
		data.put("clazzName", newEntity);
		data.put("pkg", baseUrl.replace("main.java.", "") + "." + serviceStr);
		data.put("pageBeanWithPkg", baseUrl.replace("main.java.", "") + "." + utils + "." + "PageBean");
		data.put("daoNameWithPkg", baseUrl.replace("main.java.", "") + "." + daoStr + "." + newEntity + "Dao");
		data.put("pageParamWithPkg", baseUrl.replace("main.java.", "") + "." + utils + "." + "PageParam");
		// 生成主键
		String pk = getPK(table).get(0);
		data.put("pk", Tools.field2Property(pk));
		// 获取外键
		List<String> fks = getFk(table);
		List<Item> fkItemList = new ArrayList<>();

		List<Item> paramList = tableInfoList.get(table);
		for (Item item : paramList) {
			String javaType = item.getJavaType();
			String propertyName = item.getPropertyName();
			if (propertyName.equals(Tools.field2Property(pk))) {
				data.put("pkType", javaType.substring(javaType.lastIndexOf(".") + 1));// 主键的数据类型
			}
			if (fks.contains(item.getFieldName())) {
				fkItemList.add(item);
			}
		}
		data.put("fkItemList", fkItemList);

		String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + serviceStr + "\\" + newEntity
				+ "Service.java";
		Writer out = new FileWriter(new File(fileName));
		FreemarkerUtil.execute(Constant.serviceFile, data, out);
	}
}

private void createServiceImplFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型

	for (String table : tableInfoList.keySet()) {
		String newEntity = Tools.getEntryName(table);
		// 生成类所对应的package语句
		data.put("clazzNameWithPkg", baseUrl.replace("main.java.", "") + "." + entityStr + "." + newEntity);
		data.put("serviceNameWithPkg",
				baseUrl.replace("main.java.", "") + "." + serviceStr + "." + newEntity + "Service");
		data.put("daoNameWithPkg", baseUrl.replace("main.java.", "") + "." + daoStr + "." + newEntity + "Dao");
		data.put("daoImplNameWithPkg",
				baseUrl.replace("main.java.", "") + "." + daoStr + "." + implStr + "." + newEntity + "DaoImpl");
		data.put("pageParamWithPkg", baseUrl.replace("main.java.", "") + "." + utils + "." + "PageParam");
		data.put("clazzName", newEntity);
		data.put("pkg", baseUrl.replace("main.java.", "") + "." + serviceStr + "." + implStr);
		data.put("pageBeanWithPkg", baseUrl.replace("main.java.", "") + "." + utils + "." + "PageBean");

		// 生成主键
		String pk = getPK(table).get(0);
		data.put("pk", Tools.field2Property(pk));
		// 获取外键
		List<String> fks = getFk(table);
		List<Item> fkItemList = new ArrayList<>();

		List<Item> propertyList = new ArrayList<>(); // 用来生成各属性
		List<Item> paramList = tableInfoList.get(table);
		for (Item item : paramList) {
			String javaType = item.getJavaType();
			String propertyName = item.getPropertyName();
			if (propertyName.equals(Tools.field2Property(pk))) {
				data.put("pkType", javaType.substring(javaType.lastIndexOf(".") + 1));// 主键的数据类型
			}
			if (fks.contains(item.getFieldName())) {
				fkItemList.add(item);
			}
			propertyList.add(new Item(javaType.substring(javaType.lastIndexOf(".") + 1),
					Tools.field2Property(propertyName), item.getComment()));
		}
		data.put("fkItemList", fkItemList);
		data.put("propertyList", propertyList);
		String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + serviceStr + "\\" + implStr + "\\"
				+ newEntity + "ServiceImpl.java";
		Writer out = new FileWriter(new File(fileName));
		FreemarkerUtil.execute(Constant.serviceImplFile, data, out);
	}
}

private void createPageBeanFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型
	data.put("pkg", baseUrl.replace("main.java.", "") + "." + utils);
	data.put("pageParamWithPkg", baseUrl.replace("main.java.", "") + "." + utils + "." + "PageParam");
	
	String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + utils + "\\" + "PageBean.java";

	Writer out = new FileWriter(new File(fileName));
	FreemarkerUtil.execute(Constant.pageBeanFile, data, out);
}

private void createPageParamFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型
	data.put("pkg", baseUrl.replace("main.java.", "") + "." + utils);
	
	String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + utils + "\\" + "PageParam.java";
	
	Writer out = new FileWriter(new File(fileName));
	FreemarkerUtil.execute(Constant.pageParamFile, data, out);
}

private void createConstFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型
	data.put("pkg", baseUrl.replace("main.java.", "") + "." + utils);

	String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + utils + "\\" + "Const.java";
	Writer out = new FileWriter(new File(fileName));
	FreemarkerUtil.execute(Constant.constFile, data, out);
}

private void createDBUtilFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型
	data.put("pkg", baseUrl.replace("main.java.", "") + "." + utils);

	String fileName = base + "\\" + baseUrl.replace(".", "\\") + "\\" + utils + "\\" + "DBUtil.java";
	Writer out = new FileWriter(new File(fileName));
	FreemarkerUtil.execute(Constant.dbutilFile, data, out);
}

private void createDBCPCfgFile() throws Exception {
	Map<String, Object> data = new HashMap<>(); // 创建数据模型
	data.put("databaseName", databaseName);
	data.put("username", username);
	data.put("password", password);

	String path = null;
	if (!base.contains(".")) {
		path = base + "\\resources\\";
	} else {
		path = base + "\\" + baseUrl.substring(0, baseUrl.indexOf('.')) + "\\" + "resources\\";
	}
	File file = new File(path);
	if (!file.exists()) {
		file.mkdir();
	}
	String fileName = path + "druid.properties";
	Writer out = new FileWriter(new File(fileName));
	FreemarkerUtil.execute(Constant.druidFile, data, out);
}

}

7、代码生成器入口类:App.java

public class App extends JFrame {

	private static final long serialVersionUID = 1L;

	private JTextField databaseNameTF = new JTextField("db_test", 20);// todo 产品中前面的数据库名称要去掉
	private JTextField usernameTF = new JTextField("root", 20);
	private JTextField passwordTF = new JTextField("root", 20);
	private JTextField baseUrlTF = new JTextField("com.hc", 20);
	private JTextField entityStrTF = new JTextField("entity", 20);
	private JTextField daoStrTF = new JTextField("dao", 20);
	private JTextField serviceStrTF = new JTextField("service", 20);
	private JTextField controllerStrTF = new JTextField("controller", 20);
	private JTextField implStrTF = new JTextField("impl", 20);
	private JTextField utilsStrTF = new JTextField("utils", 20);
	private JTextField sourcePathTF = new JTextField("d:/abc", 20);
	private JButton btn = new JButton("生成代码");

	public App() {
		Box vbox = Box.createVerticalBox();// 创建一个垂直箱子,这个箱子将两个水平箱子添加到其中,创建一个横向 glue 组件。

		setTitle("DBUtils代码生成器");
		setSize(335, 294);
		setLayout(new FlowLayout());

		Box hbox1 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox1.add(new JLabel("数据库名称")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox1.add(Box.createHorizontalStrut(10));
		hbox1.add(databaseNameTF);
		vbox.add(hbox1);

		Box hbox2 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox2.add(new JLabel("用户名")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox2.add(Box.createHorizontalStrut(10));
		hbox2.add(usernameTF);
		vbox.add(hbox2);

		Box hbox3 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox3.add(new JLabel("密码")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox3.add(Box.createHorizontalStrut(10));
		hbox3.add(passwordTF);
		vbox.add(hbox3);

		Box hbox5 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox5.add(new JLabel("基本路径")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox5.add(Box.createHorizontalStrut(10));
		hbox5.add(baseUrlTF);
		vbox.add(hbox5);

		Box hbox6 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox6.add(new JLabel("实体类包路径")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox6.add(Box.createHorizontalStrut(10));
		hbox6.add(entityStrTF);
		vbox.add(hbox6);

		Box hbox7 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox7.add(new JLabel("dao包路径")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox7.add(Box.createHorizontalStrut(10));
		hbox7.add(daoStrTF);
		vbox.add(hbox7);

		Box hbox8 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox8.add(new JLabel("service包路径")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox8.add(Box.createHorizontalStrut(10));
		hbox8.add(serviceStrTF);
		vbox.add(hbox8);

		Box hbox88 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox88.add(new JLabel("controller包路径")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox88.add(Box.createHorizontalStrut(10));
		hbox88.add(controllerStrTF);
		vbox.add(hbox88);

		Box hbox9 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox9.add(new JLabel("impl包路径")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox9.add(Box.createHorizontalStrut(10));
		hbox9.add(implStrTF);
		vbox.add(hbox9);

		Box hbox10 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox10.add(new JLabel("utils包路径")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox10.add(Box.createHorizontalStrut(10));
		hbox10.add(utilsStrTF);
		vbox.add(hbox10);

		Box hbox4 = Box.createHorizontalBox();// 创建一个水平箱子
		hbox4.add(new JLabel("目标代码位置")); // 在水平箱子上添加一个标签组件,并且创建一个不可见的、20个单位的组件。在这之后再添加一个文本框组件
		hbox4.add(Box.createHorizontalStrut(10));
		hbox4.add(sourcePathTF);
		vbox.add(hbox4);

		getContentPane().add(vbox);
		getContentPane().add(btn);

		setLocationRelativeTo(null);
		setVisible(true);
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	private static String utils;

	// 自动生成配置信息
	private static String databaseName;
	private static String username;
	private static String password;

	protected static String baseUrl;
	protected static String controllerStr;
	protected static String serviceStr;
	protected static String entityStr;
	protected static String implStr;
	protected static String daoStr;
	protected static String sourcePath;

	public static void main(String[] args) {
		App frame = new App();
		frame.btn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				databaseName = frame.databaseNameTF.getText().trim();
				username = frame.usernameTF.getText().trim();
				password = frame.passwordTF.getText().trim();

				utils = frame.utilsStrTF.getText().trim();

				baseUrl = frame.baseUrlTF.getText().trim();
				serviceStr = frame.serviceStrTF.getText().trim();
				entityStr = frame.entityStrTF.getText().trim();
				controllerStr = frame.controllerStrTF.getText().trim();

				implStr = frame.implStrTF.getText().trim();
				daoStr = frame.daoStrTF.getText().trim();

				sourcePath = frame.sourcePathTF.getText().trim();

				try {
					new GenerateUtil(databaseName, username, password, utils, baseUrl, controllerStr, serviceStr,
							entityStr, implStr, daoStr, sourcePath).createClassByMySqlTable();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				int i = JOptionPane.showConfirmDialog(null, "代码生成成功", "标题", JOptionPane.WARNING_MESSAGE);
				if (i == JOptionPane.OK_OPTION) {
					System.exit(0);
				}
			}
		});

	}
}