在上一篇文章 代码自动生成(一)中废了很多话,下面注解入正题:
首先定义列Col类,积累列中相应的信息,具体如下:
public class Col {
private Integer index;
private String name;
private String fieldName;
private String methodName;
private String desc;
private Type type;
private String default_;
private String isPK = "no";
private String allowNull = "no";
private Boolean hasNext = true;
/** 基本参数的构造
* @author hym
* @time 2017年7月20日 下午7:37:27
* @param index
* @param fieldName
* @param type
*/
public Col(Integer index,String fieldName,Type type){
this.index=index;
this.fieldName=fieldName;
this.type=type;
}
/**构造校验
* @author hym
* @time 2017年7月22日 下午5:19:20
* @param tab
* @param index
* @param defs
* @param isColMap
*/
public Col(String tab, int index, List
public class Type {
private String sqlType;
private String javaType;
private static HashMap typeMap=new HashMap<>();
static{
//基本的sql数据类型
typeMap.put("VARCHAR", "String");
typeMap.put("CHAR", "String");
typeMap.put("BLOB", "byte[]");
typeMap.put("TEXT", "String");
typeMap.put("INT", "Integer");
typeMap.put("INT UNSIGNED", "Integer");
typeMap.put("INTEGER", "Long");
typeMap.put("INTEGER UNSIGNED", "Long");
typeMap.put("TINYINT", "Integer");
typeMap.put("TINYINT UNSIGNED", "Integer");
typeMap.put("SMALLINT", "Integer");
typeMap.put("SMALLINT UNSIGNED", "Integer");
typeMap.put("MEDIUMINT", "Integer");
typeMap.put("MEDIUMINT UNSIGNED", "Integer");
typeMap.put("FLOAT", "Float");
typeMap.put("FLOAT UNSIGNED", "Float");
typeMap.put("DOUBLE", "Double");
typeMap.put("BIT", "Boolean");
typeMap.put("BIGINT", "java.math.BigInteger");
typeMap.put("DECIMAL", "java.math.BigDecimal");
typeMap.put("BOOLEAN", "Long");
typeMap.put("DATE", "java.sql.Date");
typeMap.put("TIME", "java.sql.Time");
typeMap.put("DATETIME", "java.sql.Timestamp") ;
typeMap.put("TIMESTAMP", "java.sql.Timestamp");
typeMap.put("YEAR", "java.sql.Date");
typeMap.put("OTHER", "String");
}
/**
* @author hym
* @time 2017年7月20日 下午5:21:52
* @param sqlType
* @param javaType
*/
public Type(String sqlType, String javaType) {
this.sqlType = sqlType.toLowerCase();
this.javaType = javaType;
}
public String getSqlType() {
return sqlType;
}
public void setSqlType(String sqlType) {
this.sqlType = sqlType;
}
public String getJavaType() {
return javaType;
}
public void setJavaType(String javaType) {
this.javaType = javaType;
}
/**
* 当返回值找不到的时候,直接返回other-string
* @author hym
* @time 2017年7月20日下午5:22:09
* @param sqlType
* @return
*/
public static Type get(String sqlType) {
String javaType=typeMap.get(sqlType.toUpperCase());
if (StringUtils.isEmpty(javaType)) {
javaType=typeMap.get("OTHER");
}
Type result = new Type(sqlType, javaType);
return result;
}
}
public class AutoGenerationJavaCode {
private String url;
private String name;
private String passWord;
private String driver;
private String sql;
private String tableName;
private String templateDir;
private String autoGeneratedFile;
//包的基础路径 比如com.xx等
private String basePath;
private static String[][] fileNameArray = new String[6][2];
static {
fileNameArray[0][0] = "entityTemplate.ftl";
fileNameArray[0][1] = ".java";
fileNameArray[1][0] = "serviceTemplate.ftl";
fileNameArray[1][1] = "Service.java";
fileNameArray[2][0] = "serviceImplTemplate.ftl";
fileNameArray[2][1] = "ServiceImpl.java";
fileNameArray[3][0] = "daoTemplate.ftl";
fileNameArray[3][1] = "Dao.java";
fileNameArray[4][0] = "daoImplTemplate.ftl";
fileNameArray[4][1] = "DaoImpl.java";
fileNameArray[5][0] = "mapper.ftl";
fileNameArray[5][1] = "Mapper.xml";
}
public AutoGenerationJavaCode(String url, String name, String passWord, String driver, String tableName,
String autoGeneratedFile,String basePath) {
this.url = url;
this.name = name;
this.passWord = passWord;
this.driver = driver;
this.sql = "select * from " + tableName;
this.tableName = tableName;
this.templateDir = this.getClass().getResource("").getPath().replace("target/classes/com/xx/common/code/autocode/", "")
+"src/main/java/com/xx/common/code/template";
this.autoGeneratedFile = autoGeneratedFile;
this.basePath=basePath;
}
public void autoGenerationJavaCode() throws IOException, TemplateException, ClassNotFoundException,
SQLException {
Configuration cfg = new Configuration();
cfg.setDefaultEncoding("utf-8");
String className = dealClassName(dealTableName());
String fileName = className;
// Map columnMap = getColumn();
//设置模板文件路径
cfg.setDirectoryForTemplateLoading(new File(templateDir));
Map rootMap = new HashMap();
rootMap.put("className", className);
//rootMap.put("columnMap", columnMap);
rootMap.put("columns", getColumnList());
rootMap.put("basePath", basePath);
for (int i = 0; i < fileNameArray.length; i++) {
String packageName=null;
String filePath=null;
//设定包名
switch(fileNameArray[i][0]){
case "entityTemplate.ftl":
packageName=basePath+".entity";
filePath=autoGeneratedFile+"/entity";
break;
case "daoTemplate.ftl":
packageName=basePath+".dao";
filePath=autoGeneratedFile+"/dao";
break;
case "daoImplTemplate.ftl":
packageName=basePath+".dao.impl";
filePath=autoGeneratedFile+"/dao/impl";
break;
case "serviceTemplate.ftl":
packageName=basePath+".service";
filePath=autoGeneratedFile+"/service";
break;
case "serviceImplTemplate.ftl":
packageName=basePath+".service.impl";
filePath=autoGeneratedFile+"/service/impl";
break;
case "mapper.ftl":
packageName=basePath;
filePath=autoGeneratedFile+"/mapper";
rootMap.put("tableName", tableName);
break;
}
rootMap.put("packageName", packageName);
File dir=new File(filePath);
//检查目录是否存在,不存在则创建
if (!dir.exists()) {
dir.mkdir();
}
Template temp = cfg.getTemplate(fileNameArray[i][0]);
File docFile = new File(filePath + "//" + fileName + fileNameArray[i][1]);
Writer docout = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
//输出文件
temp.process(rootMap, docout);
}
System.out.println("==============所有的文件已成功生成===============");
}
public List getColumnList() throws ClassNotFoundException, SQLException {
Connection conn;
PreparedStatement pStemt = null;
Class.forName(driver);
conn = DriverManager.getConnection(url, name, passWord);
pStemt = conn.prepareStatement(sql);
ResultSetMetaData rsmd = pStemt.getMetaData();
List listColumn=new ArrayList ();
int size = rsmd.getColumnCount();
for (int i = 0; i < size; i++) {
// String columnName = dealColumnName(rsmd, i);
Col col=getColumnInfo(rsmd, i);
if(i==size-1){
col.setHasNext(false);
}
listColumn.add(col);
}
conn.close();
return listColumn;
}
/**
* 获取列信息 需要设置多属性,该处生成mapper.xml的时候需要各种属性
* @author hym
* @time 2017年7月20日下午7:48:39
* @param rsmd
* @param i
* @return
* @throws SQLException
*/
private Col getColumnInfo(ResultSetMetaData rsmd,int i) throws SQLException{
String columnName = rsmd.getColumnName(i + 1).toLowerCase();
String charAfterLine = String.valueOf(columnName.charAt((columnName.indexOf("_") + 1)));
String convertedChar = charAfterLine.toUpperCase();
String fieldName = columnName.replace("_" + charAfterLine, convertedChar);//映射到类中的名称
String columntype=rsmd.getColumnTypeName(i+1);//sql的列类型
Type type=new Type(columntype, Type.get(columntype).getJavaType());
Col col=new Col(i, fieldName, type);
col.setMethodName(dealClassName(fieldName));
col.setName(columnName);//表中的列名
if (columnName.equalsIgnoreCase("id")) {
col.setPK("yes");
}
return col;
}
/**
* 将表名转换为DMO的字段名,比如 operate_type 转换后为 operateType
* @author hym
* @time 2017年7月22日下午4:22:14
* @param rsmd
* @param i
* @return
* @throws SQLException
*/
private String dealColumnName(ResultSetMetaData rsmd, int i) throws SQLException {
String columnName = rsmd.getColumnName(i + 1).toLowerCase();
String charAfterLine = String.valueOf(columnName.charAt((columnName.indexOf("_") + 1)));
String convertedChar = charAfterLine.toUpperCase();
columnName = columnName.replace("_" + charAfterLine, convertedChar);
return columnName;
}
/**
* 将表名转换为类型类名 比如 t_operate_log 转换后为 operateLog ,类名首字母应为大写,这里在freemarker的模板里直接转换
* @author hym
* @time 2017年7月22日下午4:22:05
* @return
*/
private String dealTableName() {
String className = tableName.toLowerCase().substring(tableName.indexOf("_") + 1);
String charAfterLine = String.valueOf(className.charAt((className.indexOf("_") + 1)));
String convertedChar = charAfterLine.toUpperCase();
className = className.replace("_" + charAfterLine, convertedChar);
return className;
}
public static void main(String[] args) {
String tableName="t_operate_table_test";
String className = tableName.toLowerCase().substring(tableName.indexOf("_") + 1);
String charAfterLine = String.valueOf(className.charAt((className.indexOf("_") + 1)));
String convertedChar = charAfterLine.toUpperCase();
className = className.replace("_" + charAfterLine, convertedChar);
}
/**
* 将类名转换为文件名,java公共类名与其文件名应该相同,这里将首字母转换为大写 如operateLog 转换后为 OperateLog
* @author hym
* @time 2017年7月22日下午4:22:25
* @param className
* @return
*/
private String dealClassName(String className) {
String first = className.substring(0, 1).toUpperCase();
String rest = className.substring(1, className.length());
String fileName = new StringBuffer(first).append(rest).toString();
return fileName;
}
}
Ok,上面的基本完成了生成所需的java类文件;
测试代码如下:
public static void main(String[] args) throws ClassNotFoundException, IOException, TemplateException, SQLException {
String url="jdbc:mysql://10.67.18.17:3306/xx";
String username="xx";
String password="xx";
String driver="com.mysql.jdbc.Driver";
String tableName="t_test_operate";
String basePath="com.xx.test";
String templateDir=System.getProperty("user.dir")+"/src/main/java/"+"com/xx/common/code/template";
String generateFilePath=System.getProperty("user.dir")+"/src/main/java/"+basePath.replace(".", "/");
AutoGenerationJavaCode autoGenerationJavaCode=
new AutoGenerationJavaCode(url, username, password, driver, tableName, generateFilePath, "com.xx.test");
autoGenerationJavaCode.autoGenerationJavaCode();
}
考虑到可能会用到不同类型的数据库,后面会对上面的类进行改造;