论坛首页 Java企业应用论坛

代码生成工具的实现思路

浏览 9715 次
精华帖 (0) :: 良好帖 (3) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-01-03   最后修改:2012-01-04
1.利用 JDBC中的 ResultSetMetaData 和 DatabaseMetaData  来读取表字段的相关信息

DataSource dataSource = context.getBean("dataSource", DataSource.class);
		Connection conn = dataSource.getConnection();
		List<Column> lsColumns = new ArrayList<Column>(10);
		PreparedStatement stmt = conn.prepareStatement("select *  from "+tableName+" where 1=0 ");
		ResultSet resultSet = stmt.executeQuery();
		ResultSetMetaData rsmd = resultSet.getMetaData();
		int n = rsmd.getColumnCount();
		for (int i = 1; i <= n; i++)
		{
			String colName = rsmd.getColumnName(i);
			String fieldName = StringUtil.toBeanPatternStr(colName);
			Column column = new Column();
			column.setName(colName) ;
			column.setJavaName(fieldName) ;
			column.setDataType(rsmd.getColumnClassName(i));
			column.setPrecision(String.valueOf(rsmd.getPrecision(i)));
			column.setScale( String.valueOf(rsmd.getScale(i)) );
			column.setLength( String.valueOf(rsmd.getColumnDisplaySize(i)));
			column.setNullable(String.valueOf("1".equals(rsmd.isNullable(i))));

//获取列注释
			DatabaseMetaData dbmd = conn.getMetaData();
			ResultSet rs = dbmd.getColumns(null, null, tableName, null);
			while (rs.next()) {
				if (colName.equals(rs.getString("COLUMN_NAME")))
					column.setComments(rs.getString("REMARKS"));
			}
			//获取主键列
			ResultSet rs2 = dbmd.getPrimaryKeys(null, null, tableName);
			while (rs2.next()) {
				if (colName.equals(rs2.getString("COLUMN_NAME")))
					column.setColumnKey("TRUE");	
			}


2.讲表字段相关信息放入模板引擎的上下文中,根据模板内容生成JAVA文件;

	Velocity.addProperty("file.resource.loader.path", getClassPath()
				+ tmplDir);
		Template template = Velocity.getTemplate(tmplFile, encoding);
		VelocityContext tmplContext = new VelocityContext(context);
		FileUtil.createFile(absolutePath);
		PrintWriter writer = new PrintWriter(
				new FileOutputStream(absolutePath), true);
		template.merge(tmplContext, writer);
		writer.flush();
		writer.close();


3.tmplFile模板文件的内容如下:

 #if($pkResult.size()>1)
     @EmbeddedId
     #else
     @Id
     @Column(name = "$pkResult.get(0).name"  )
     @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="${TABLE_NAME}_SEQ") 
     #end
     private ${keyType}  ${keyVar} ;

     #foreach($prop in $columnResult)
        #set ($fieldName  = ${prop.javaName} )
        #set ($fieldType  = $prop.dataType )
        @Column(name = "${prop.name}" )
    	private $fieldType $fieldName ;
	
     #end


     public  ${keyType} get${KeyFieldUpper} () {
		return ${keyVar};
     }

     public void set${KeyFieldUpper} (${keyType}  ${keyVar}) {
		this.${keyVar} = ${keyVar};         
      }

     #foreach($prop in $columnResult)
        #set ($fieldName  = ${prop.javaName} )
        #set ($fieldType  =  $prop.dataType )
        #set ($innerFieldUpper  = $stringUtil.capitalize($fieldName) )
	public $fieldType get$innerFieldUpper () {
		return $fieldName;
	}
	public void set$innerFieldUpper ($fieldType $fieldName) {
		this.$fieldName = $fieldName;		
	}
     #end


代码路径:


  • 大小: 65.1 KB
   发表时间:2012-01-04  
你这是velocity吧,不过这种操作应该包含javabean的生成
0 请登录后投票
   发表时间:2012-01-04  
jyjava 写道
你这是velocity吧,不过这种操作应该包含javabean的生成

是的。也可以使用其他模块框架,freemarker也可以的。
0 请登录后投票
   发表时间:2012-01-05  
代码生成器本身并没什么难度,只要能抽象出代码模型来,用freemarker类似的东西搞一下就行,主要是架构风格的问题
0 请登录后投票
   发表时间:2012-01-05  
写的很好,也很实用

目前已经有的代码生成工具,类似于middgen,ibatior之类的,可以考虑一下改装

我以前在公司就改装过一个类似的,是通过middgen改装的,如果什么都自己写,感觉太累了
0 请登录后投票
   发表时间:2012-01-05  
我用 CODESMITH   挺好用的。。  只不过模板是C#语法。但是网络上很多。
0 请登录后投票
   发表时间:2012-01-05  
这个东西写个适合工作使用的就行了
0 请登录后投票
   发表时间:2012-01-05  
senvon 写道
写的很好,也很实用

目前已经有的代码生成工具,类似于middgen,ibatior之类的,可以考虑一下改装

我以前在公司就改装过一个类似的,是通过middgen改装的,如果什么都自己写,感觉太累了


拼写都错误诶。。iBATOR
0 请登录后投票
   发表时间:2012-01-05  

核心技术是模板引擎..

最近用node.js写了个Struts Action + 配置的生成工具.

模板用的 Mustache
http://mustache.github.com/

可以试试这个模板引擎.
模板文件基本都是*.java, *.xml

 

@Log4j
@Getter@Setter
@SuppressWarnings("serial")
@Component("{{actionName}}Action")
public class {{ActionClass}} extends AppAction {

	private String id = null;
	
	private {{ServiceClass}} {{serviceId}} = null;
	
	private {{DomainClass}}{{domainSuffix}} {{domainName}} = new {{DomainClass}}{{domainSuffix}}();
	
	public String index() {
		log.debug("execute index...");
		return "index";
	}
	
	public String show() {
		log.debug("execute show...");
		return "show";
	}
	
	public String create() {
		log.debug("execute create...");
		{{domainName}} = new {{DomainClass}}{{domainSuffix}}();
		return "create";
	}
	
	public String save() {
		log.debug("execute save...");
		return "show";
	}
	
	public String edit() {
		log.debug("execute edit...");
		return "edit";
	}
	
	public String update() {
		log.debug("execute update...");
		return "show";
	}
	
	public String remove() {
		log.debug("execute remove...");
		return "list";
	}
	
	public String search() {
		log.debug("execute search...");
		return "list";
	}
}

 

生成代码比较easy:

 

// TODO 从tmpls中读取文件
fs.readFile(actionPath, "UTF-8", function(err, data) {
	if (err) throw err;
	
	var actionCode = Mustache.to_html(data, vals);
	console.log(actionCode)
	
	fs.writeFile(targetPath + vals.ActionClass + ".java", actionCode, function(err) {
		if(err) throw err;
		
		console.log("generate " + vals.ActionClass + ".java success!");
	});
})

 

0 请登录后投票
   发表时间:2012-01-05  
要能前后台一体化生成,后台,页面。都生成好了。后台加上注解。连配置文件都可以极大的节省。主要是通过读取你要做的功能的表(可以是多个表关联)的字段,生成模板文件。然后通过el表达式替换掉模板里面的模块名称。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics