自己利用spring3、mybatis3进行开发时,前期花费了大量的时间去写对应的model、mapper、service文件,并想到用freemarker来动态生成对应的JAVA文件.
开发思路:
其实就是将数据库中的表取出来,表名作为类名,并把对应的列名取出来,作为字段名称,然后通过 freemarker定制的模版去生成相关的文件即可。
我这里只举例说明如何生成对应的model文件,其它的可以直接COPY改改就成,示例代码如下:
首先定义一个对象SqlColumnData包含两个属性columnName(列名称),columnType(列类型),具体定义如下 :
1 package org.study.job.domain; 2 /** 3 * SqlColumnData.java Create on 2012-6-15上午10:37:47 4 * 5 * 6 * Copyright (c) 2012 by MTA. 7 * 8 * @author lmeteor 9 * @Email txin0814@sina.com 10 * @description 11 * @version 1.0 12 */ 13 public class SqlColumnData 14 { 15 16 private String columnName; 17 18 private String columnType; 19 20 public String getColumnName() 21 { 22 return columnName; 23 } 24 25 public void setColumnName(String columnName) 26 { 27 this.columnName = columnName; 28 } 29 30 public String getColumnType() 31 { 32 return columnType; 33 } 34 35 public void setColumnType(String columnType) 36 { 37 this.columnType = columnType; 38 } 39 40 41 }
下面三个方法作用如下:
//用来获取指定表的所有列名及类型 public List<SqlColumnData> getColumnDatas(String tableName) //将列名生成对应的field 和 method public String getBeanField(String tableName) throws SQLException //将数据库类型转换成对应的JAVA类型 publicString getType(String type)
1 /** 2 * 获取指定表的所有列名 3 * 4 * @param tableName 5 * @return 6 * @throws SQLException 7 */ 8 public List<SqlColumnData> getColumnDatas(String tableName) 9 throws SQLException 10 { 11 String sqlColumns = "SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.columns WHERE table_name = '" 12 + tableName + "' order by ordinal_position"; 13 Connection conn = null; 14 PreparedStatement pst = null; 15 ResultSet rs = null; 16 List<SqlColumnData> columnList = new ArrayList<SqlColumnData>(); 17 try 18 { 19 conn = sqlDialect.getConn(); 20 pst = conn.prepareStatement(sqlColumns); 21 rs = pst.executeQuery(); 22 while (rs.next()) 23 { 24 String name = rs.getString(1); 25 String type = rs.getString(2); 26 type = this.getType(type); 27 SqlColumnData cd = new SqlColumnData(); 28 cd.setColumnName(name.toLowerCase()); 29 cd.setColumnType(type); 30 columnList.add(cd); 31 } 32 33 } 34 catch ( Exception e ) 35 { 36 e.printStackTrace(); 37 } 38 finally 39 { 40 try 41 { 42 if (conn != null) conn.close(); 43 if (pst != null) pst.close(); 44 if (rs != null) rs.close(); 45 } 46 catch ( SQLException e ) 47 { 48 e.printStackTrace(); 49 } 50 } 51 return columnList; 52 } 53 54 /** 55 * 将列名生成对应的field 和 method 56 * 57 * @param tableName 58 * @return 59 * @throws SQLException 60 */ 61 public String getBeanField(String tableName) throws SQLException 62 { 63 List<SqlColumnData> dataList = getColumnDatas(tableName); 64 StringBuffer str = new StringBuffer(); 65 StringBuffer getset = new StringBuffer(); 66 for (SqlColumnData d : dataList) 67 { 68 String name = d.getColumnName().toLowerCase(); 69 String type = d.getColumnType(); 70 String maxChar = name.substring(0, 1).toUpperCase(); 71 str.append("\r\t").append("private ").append(type + " ").append( 72 name).append(";\n"); 73 String method = maxChar + name.substring(1, name.length()); 74 getset.append("\r\t").append("public ").append(type + " ").append( 75 "get" + method + "()\n\t{\n"); 76 getset.append("\t\t").append("return this.").append(name).append(";\n\t}\n"); 77 getset.append("\r\t").append("public void ").append( 78 "set" + method + "(" + type + " " + name + ")\n\t{\n"); 79 getset.append("\t\t").append("this." + name + "=").append(name).append( 80 ";\n\t}\n"); 81 } 82 argv = str.toString(); 83 method = getset.toString(); 84 return argv + method; 85 } 86 87 private String argv; 88 private String method; 89 90 /** 91 * 将数据库类型转换成对应的JAVA类型 92 * 93 * @param type 94 * @return 95 */ 96 public String getType(String type) 97 { 98 type = type.toLowerCase(); 99 if ("char".equals(type) || "varchar".equals(type) 100 || "nvarchar".equals(type)) 101 { 102 return "String"; 103 } 104 else if ("int".equals(type)) 105 { 106 return "Integer"; 107 } 108 else if ("bigint".equals(type)) 109 { 110 return "Long"; 111 } 112 else if ("timestamp".equals(type) || "date".equals(type) 113 || "datetime".equals(type)) 114 { 115 return "java.sql.Timestamp"; 116 } 117 else if ("decimal".equals(type)) 118 { 119 return "Double"; 120 } 121 else if ("image".equals(type)) 122 { 123 return "byte[]"; 124 } 125 else if ("smallint".equals(type)) 126 { 127 return "int"; 128 } 129 return null; 130 }
/** * 将表名转成class名称 * * @param tableName * @return */ public String getTableNameToClassName(String tableName) { String[] splits = tableName.toLowerCase().split("_"); if (splits.length > 0) { StringBuffer className = new StringBuffer(); for (String split : splits) { String tempTableName = split.substring(0, 1).toUpperCase() + split.substring(1); className.append(tempTableName); } return className.toString(); } else { String className = splits[0].substring(0, 1).toUpperCase() + splits[0].substring(1); return className; } }
SQL方面就准备的差不多了,现在开始准备对应的模版文件,如下:
我这里使用的freemarker
1 package org.study.job.domain; 2 3 import java.io.Serializable; 4 /** 5 * ${className?default('')}.java Create on ${datetime?default('')} 6 * 7 * 8 * Copyright (c) 2012 by MTA. 9 * 10 * @author lmeteor 11 * @Email txin0814@sina.com 12 * @description 13 * @version 1.0 14 */ 15 @SuppressWarnings("serial") 16 public class ${className?default('')} implements Serializable 17 { 18 ${feilds?default('')} 19 }
用freemarker通过模版创建文件:
1 /** 2 * 创建静态文件 3 * 4 * @param templateFileName 5 * 模板文件名,例如:/WEB-INF/view/temp.ftl 6 * @param propMap 7 * 用于处理模板的属性object映射 8 * @param htmlFilePath 9 * 要生成的静态文件的路径,例如:/WEB-INF/view/1/2012/5/5 10 * @param htmlFileName 11 * 要生成的文件名:例如:1.html 12 * @param templateFilePath 13 * 模版路径 14 */ 15 @SuppressWarnings( 16 { "unchecked" }) 17 public static void createHtmlFile(String templateFileName, Map propMap, 18 String htmlFilePath, String htmlFileName, String templateFilePath) 19 { 20 try 21 { 22 Template t = getFreemarkerCFG(templateFilePath).getTemplate( 23 templateFileName); 24 //createDirs(htmlFilePath); 25 File file = null; 26 if(StringTools.isEmpty(htmlFileName))file = new File(htmlFilePath); 27 else file = new File(htmlFilePath + "/" + htmlFileName); 28 if(!file.exists())file.createNewFile(); 29 else file.delete(); 30 Writer out = new BufferedWriter(new OutputStreamWriter( 31 new FileOutputStream(file),"UTF-8")); 32 t.process(propMap, out); 33 out.flush(); 34 out.close(); 35 logger.info("文件:"+htmlFilePath+"生成成功。"); 36 } 37 catch ( IOException e ) 38 { 39 e.printStackTrace(); 40 } 41 catch ( TemplateException e ) 42 { 43 e.printStackTrace(); 44 } 45 }
现在该准备的都准备好了,准备开始实际调用如下
1 /** 2 * 生成JAVAMODULE文件 3 * @param tableName 4 */ 5 public static void createJavaModuleFile(String tableName) 6 { 7 String className = sqlutil.getTableNameToClassName(tableName); 8 // 生成到指定的目录下 9 String modelPath = "domain\\" + className + ".java"; 10 Map<String,Object> context = new HashMap<String,Object>(); 11 context.put("className", className); // 12 context.put("tableName", tableName); 13 context.put("datetime", DateTools.getDateTools().format(new Date())); 14 /****************************** 生成bean字段 *********************************/ 15 try 16 { 17 context.put("feilds", sqlutil.getBeanField(tableName)); // 生成bean 18 logger.info("请稍侯,正在生成Bean属性及GET、SET方法"); 19 } 20 catch ( Exception e ) 21 { 22 e.printStackTrace(); 23 } 24 // -------------------生成文件代码---------------------/ 25 CreateHtml.createHtmlFile("TempBean.ftl", context, PCKPATH+modelPath, null, TEMPLATE_FILEPATH); 26 }
大致代码就是这么多,我在自己的项目中将这个功能界面化了,如下:
因为我项目中对SPRING的管理都是用注解完成,所以不用去修改spring.xml文件。