代码自动生成(二)

在上一篇文章  代码自动生成(一)中废了很多话,下面注解入正题:

首先定义列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 defs, Boolean isColMap) {
    int size = defs.size();
    this.index = index;
    if (size < 2) {
      throw new RuntimeException("表'" + tab + "'的第'" + index + "'字段没有定义字段名");
    }
    name = (String) defs.get(1);
    if (name == null || name.trim().length() == 0) {
      throw new RuntimeException("表'" + tab + "'的第'" + index + "'字段没有定义字段名");
    }
    desc = (String) defs.get(2);
    if (size < 4) {
      throw new RuntimeException("表'" + tab + "'的'" + name + "'字段没有定义类型");
    }
    String typeStr = (String) defs.get(3);
    if (typeStr == null || typeStr.trim().length() == 0) {
      throw new RuntimeException("表'" + tab + "'的'" + name + "'字段没有定义字类型");
    }
    typeStr = typeStr.trim().toLowerCase();
    type = Type.get(typeStr);
    if (type == null) {
      throw new RuntimeException("表'" + tab + "'的'" + name + "'字段类型定义错误");
    }
    fieldName = format();
    if (size >= 6) {
      default_ = defs.get(5).toString().trim();
      if (default_.length() == 0) {
        default_ = null;
      }
    }
    if (size >= 7) {
      isPK = defs.get(6).toString().trim().toLowerCase();
      if (isPK.length() == 0) {
        isPK = "no";
      }
    }
    if (size >= 8) {
      allowNull = defs.get(7).toString().trim().toLowerCase();
      if (allowNull.length() == 0) {
        allowNull = "no";
      }
    }
    if (isColMap) {
      name = removeDBKeyword(name);
    }
  }

  public Integer getIndex() {
    return index;
  }

  public void setIndex(Integer index) {
    this.index = index;
  }

  public String getName() {
    return new StringBuffer(name).toString();
  }

  public String getFieldName() {
    return fieldName;
  }

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

  public String getMethodName() {
    return methodName;
  }

  public void setMethodName(String methodName) {
    this.methodName = methodName;
  }

  private String format() {
    String _name = this.getName();
    int idx = -1;
    while ((idx = _name.indexOf("_")) != -1) {
      String pre = _name.substring(0, idx);
      String tmpSuf = _name.substring(idx + 1).trim();
      String suf_ = "";
      if (tmpSuf.length() > 0) {
        String suf = tmpSuf.substring(0, 1).toUpperCase();
        if (tmpSuf.length() > 1) {
          suf_ = suf + tmpSuf.substring(1);
        } else {
          suf_ = suf;
        }
      }
      _name = pre + suf_;
    }
    methodName = _name.substring(0, 1).toUpperCase() + _name.substring(1);
    return _name.substring(0, 1).toLowerCase() + _name.substring(1);
  }

  private String removeDBKeyword(String name) {
    String result = name;
    if (DBKeyword.get(name.toUpperCase()) != null) {
      result = "`" + name + "`";
    }
    return result;
  }

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

  public String getDesc() {
    return desc;
  }

  public void setDesc(String desc) {
    this.desc = desc;
  }

  public Type getType() {
    return type;
  }

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

  public String getDefault() {
    return default_;
  }

  public void setDefault(String default_) {
    this.default_ = default_;
  }

  public String getIsPK() {
    return isPK;
  }

  public void setPK(String isPK) {
    this.isPK = isPK;
  }

  public String getIsAllowNull() {
    return allowNull;
  }

  public void setAllowNull(String allowNull) {
    this.allowNull = allowNull;
  }

public Boolean getHasNext() {
	return hasNext;
}

public void setHasNext(Boolean hasNext) {
	this.hasNext = hasNext;
}
} 
  

Type类是定义mysql列数据类型和java中数据类型的转换,写的比较单一,该项可以再以后进行扩展改变,因为数据库除了mysql还有oracle,sqlserver等;

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();
	
	}


考虑到可能会用到不同类型的数据库,后面会对上面的类进行改造;


你可能感兴趣的:(java程序及相关,SpringBoot)