`
843977358
  • 浏览: 246627 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【干货】自己动手打造专属代码生成工具(完结篇)

阅读更多

图片描述
神兽坐镇!!
...
...
OK,进入主题,上篇说到了代码生成工具,只是演示了一下简单的操作流程。那么,说好了,这篇是贴码文,在贴码之前先大体说下原理吧(大神止步吧...)......

说到需要生成文件,不得不说说在项目开发中那些让码农们头疼的事:在项目开发中最让人头疼的就是把数据库表字段对应成java实体属性,一个数据库如果有几十个表,单单靠手写java实体的话,等项目上线了,估计实体刚建完图片描述...
再一个就是对数据库进行操作的mapper文件,一般的业务上都包括增删改查(批/单),以及对应实体的resultMap定义。此项工作如果没有工具的帮助,就相当于重复造轮子。因为增删改查(批/单)区别就在于表名不同、resultMap区别就在于字段不同
......
以上只是简单的举证了一下(不要嫌俺啰嗦,俺只是深恶痛绝...),说回俺这个代码生成工具,原理莫过于获取系统中的数据库列表,根据数据库获取单个数据库下的所有数据表,最后一步是最重要也是最麻烦的,要获取数据表中的字段、字段类型、字段注释等等,因为要根据字段类型生成对应的java类型变量。
(神马~~!!这TM就是所谓的原理?酱简单?你TM是不是唬我?)
没错,就是这么简单,天地良心
图片描述
下面到重点部分了,贴码!!

  • 获取所有数据库
/**
     * @Description 获取数据库列表
     * @author zhangyd
     * @date 2015年12月9日 上午10:17:33
     * @param mybatisSqlForm
     * @return
     */publicList<String> getDbNameList(TableForm mybatisSqlForm){List<String> list =newArrayList<String>();ResultSet rs =null;Connection conn =null;Statement statement =null;try{String sql ="show databases";
            rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
                    mybatisSqlForm.getDbPassword(), sql.toString());while(rs.next()){
                list.add(rs.getString(1));}}catch(SQLException e){
            e.printStackTrace();}finally{try{if(rs !=null){
                    rs.close();}}catch(SQLException e){
                e.printStackTrace();}try{if(statement !=null)
                    statement.close();}catch(SQLException e){
                e.printStackTrace();}try{if(conn !=null)
                    conn.close();}catch(SQLException e){
                e.printStackTrace();}}return list;}

获取数据库也是用的最基本的sql语句:show databases;

  • 获取数据库表列表
/**
     * @Description 获取数据库表列表
     * @author zhangyd
     * @date 2015年12月9日 上午10:17:46
     * @param mybatisSqlForm
     * @return
     */publicList<String> getTableNameList(TableForm mybatisSqlForm){List<String> list =newArrayList<String>();ResultSet rs =null;Connection conn =null;Statement statement =null;try{String sql ="SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '"+ mybatisSqlForm.getSelectedDbNames()+"'";
            rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
                    mybatisSqlForm.getDbPassword(), sql.toString());while(rs.next()){
                list.add(rs.getString(1));}}catch(SQLException e){
            e.printStackTrace();}finally{try{if(rs !=null){
                    rs.close();}}catch(SQLException e){
                e.printStackTrace();}try{if(statement !=null)
                    statement.close();}catch(SQLException e){
                e.printStackTrace();}try{if(conn !=null)
                    conn.close();}catch(SQLException e){
                e.printStackTrace();}}return list;}
  • 获取字段名 列表
/**
     * @Description 获取字段名 列表
     * @author zhangyd
     * @date 2015年12月9日 上午10:18:07
     * @param mybatisSqlForm
     * @return
     */publicList<String> getColumnNameList(TableForm mybatisSqlForm){List<String> columnNames =newArrayList<String>();ResultSet rs =null;Connection conn =null;Statement statement =null;try{StringBuffer sql =newStringBuffer();
            sql.append("SELECT DISTINCT column_name cloumnName,data_type type,column_comment comment,column_key FROM Information_schema.COLUMNS ");
            sql.append("WHERE TABLE_NAME = '"+ mybatisSqlForm.getSelectedTableNames()+"' and TABLE_SCHEMA = '"+ mybatisSqlForm.getSelectedDbNames()+"'");
            rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
                    mybatisSqlForm.getDbPassword(), sql.toString());while(rs.next()){
                columnNames.add(rs.getString(1));}}catch(SQLException e){
            e.printStackTrace();}finally{try{if(rs !=null){
                    rs.close();}}catch(SQLException e){
                e.printStackTrace();}try{if(statement !=null)
                    statement.close();}catch(SQLException e){
                e.printStackTrace();}try{if(conn !=null)
                    conn.close();}catch(SQLException e){
                e.printStackTrace();}}return columnNames;}
  • 获取数据表详情(字段类型、注释等)
/**
     * @Description 获取数据表详情
     * @author zhangyd
     * @date 2015年12月9日 上午10:19:19
     * @param mybatisSqlForm
     * @return
     */publicList<Variable> getTableInfo(TableForm mybatisSqlForm){List<Variable> tableInfo =newArrayList<Variable>();Connection conn =null;Statement statement =null;ResultSet rs =null;try{StringBuffer sql =newStringBuffer();
            sql.append("SELECT DISTINCT column_name cloumnName,data_type type,column_comment comment,column_key FROM Information_schema.COLUMNS ");
            sql.append("WHERE TABLE_NAME = '"+ mybatisSqlForm.getSelectedTableNames()+"' and TABLE_SCHEMA = '"+ mybatisSqlForm.getSelectedDbNames()+"'");
            rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
                    mybatisSqlForm.getDbPassword(), sql.toString());while(rs.next()){Variable variable =newVariable();
                variable.setColumnName(rs.getString("cloumnName"));
                variable.setType(rs.getString("type"));
                variable.setComment(rs.getString("comment"));
                variable.setColumnKey(rs.getString("column_key"));
                tableInfo.add(variable);}}catch(SQLException e){
            e.printStackTrace();}finally{try{if(rs !=null){
                    rs.close();}}catch(SQLException e){
                e.printStackTrace();}try{if(statement !=null)
                    statement.close();}catch(SQLException e){
                e.printStackTrace();}try{if(conn !=null)
                    conn.close();}catch(SQLException e){
                e.printStackTrace();}}return tableInfo;}
  • 以下这一段代码是以上三段代码需要用到的公共方法
/**
     * @Description 请求数据库链接,获取返回结果集
     * @author zhangyd
     * @date 2015年12月9日 上午10:32:22
     * @param dbAddress
     * @param userName
     * @param passWord
     * @param sql
     * @return
     */publicResultSet getResultSet(Connection conn,Statement statement,String dbAddress,String userName,String passWord,String sql){ResultSet rs =null;try{
            conn =DriverManager.getConnection(getDbUrl(dbAddress), userName, passWord);
            statement = conn.createStatement();
            rs = statement.executeQuery(sql.toString());}catch(SQLException e){
            e.printStackTrace();}return rs;}publicString getDbUrl(String dbAddress){return"jdbc:mysql://"+ dbAddress +"?useUnicode=true&characterEncoding=utf-8";}
  • 生成java文件相关业务实现
/**   
 * @Title: GenerationClassServiceImpl.java 
 * @Package: com.maven.web.service.generation.impl
 * @Description: TODO
 * @author zhangyd
 * @date 2015年11月16日 下午5:54:28 
 * @version 1.0 
 */package com.maven.web.service.generation.impl;import java.util.HashMap;import java.util.List;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.maven.web.dao.generation.GenerationMapperDao;import com.maven.web.entity.generation.TableForm;import com.maven.web.entity.generation.Variable;import com.maven.web.service.generation.IGenerationClassService;import com.maven.web.utils.FileUtil;import com.maven.web.utils.StringUtil;import com.maven.web.utils.memcache.MemcachedUtil;/**
 * @Description 生成java文件业务实现
 * @author zhangyd
 * @date 2015年12月18日 下午4:54:13
 * @version V1.0
 * @since JDK : 1.7
 * @modify
 * @Review
 */@ServicepublicclassGenerationClassServiceImplimplementsIGenerationClassService{@AutowiredprivateGenerationMapperDao generationMapperDao;// 数据库数据类型、java数据类型映射mapprivatestaticMap<String,String> dataTypeMapping =newHashMap<String,String>();// 初始化数据库类型与java类型转换static{
        dataTypeMapping.put("int","int");
        dataTypeMapping.put("tinyint","int");
        dataTypeMapping.put("smallint","int");
        dataTypeMapping.put("mediumint","int");
        dataTypeMapping.put("integer","int");
        dataTypeMapping.put("bigint","long");
        dataTypeMapping.put("bit","boolean");
        dataTypeMapping.put("real","float");
        dataTypeMapping.put("double","double");
        dataTypeMapping.put("float","float");
        dataTypeMapping.put("float","float");
        dataTypeMapping.put("decimal","BigDecimal");
        dataTypeMapping.put("numeric","BigDecimal");
        dataTypeMapping.put("char","String");
        dataTypeMapping.put("varchar","String");
        dataTypeMapping.put("date","java.util.Date");
        dataTypeMapping.put("time","java.util.Time");
        dataTypeMapping.put("year","java.util.Date");
        dataTypeMapping.put("timestamp","java.util.Timestamp");
        dataTypeMapping.put("datetime","java.util.Date");
        dataTypeMapping.put("tinyblob","byte[]");
        dataTypeMapping.put("blob","byte[]");
        dataTypeMapping.put("mediumblob","byte[]");
        dataTypeMapping.put("longblob","byte[]");
        dataTypeMapping.put("tinytext","String");
        dataTypeMapping.put("text","String");
        dataTypeMapping.put("mediumtext","String");
        dataTypeMapping.put("longtext","String");
        dataTypeMapping.put("binary","byte[]");}/**
     * @Description 生成java实体
     * @author zhangyd
     * @date 2015年12月9日 上午10:11:17
     * @param tableForm
     * @return
     */@OverridepublicMap<String,Object> getJava(TableForm tableForm){List<Variable> tableInfo = generationMapperDao.getTableInfo(tableForm);Map<String,Object> sqlMap =newHashMap<String,Object>();String sqlString = createJava(tableInfo, tableForm);
        sqlMap.put("list", sqlString);return sqlMap;}/**
     * @Description 创建java实体字符串
     * @author zhangyd
     * @date 2015年12月9日 上午10:11:22
     * @param tableInfo
     * @param tableForm
     * @return
     */@OverridepublicString createJava(List<Variable> tableInfo,TableForm tableForm){StringBuilder sb =newStringBuilder();// 包名String packageString = createPackage(tableForm.getEntityPackage());
        sb.append(packageString);// classString classString = createClass(tableForm.getSelectedTableNames());
        sb.append(classString);// 变量String variablesString = createVariables(tableInfo);
        sb.append(variablesString);// SetAndGetStringSetAndGetString= createSetAndGet(tableInfo);
        sb.append(SetAndGetString);// 尾部String tailString = createTail();
        sb.append(tailString);return sb.toString();}/**
     * @Description 创建包信息
     * @author zhangyd
     * @date 2015年12月9日 上午10:11:28
     * @param packagePath
     * @return
     */@OverridepublicString createPackage(String packagePath){StringBuilder sb =newStringBuilder();
        sb.append("package "+ packagePath +";<br><br>");return sb.toString();}/**
     * @Description 创建导入信息
     * @author zhangyd
     * @date 2015年12月9日 上午10:11:33
     * @return
     */@OverridepublicString createImport(){StringBuilder sb =newStringBuilder();
        sb.append("<br>");return sb.toString();}/**
     * @Description 创建class名
     * @author zhangyd
     * @date 2015年12月9日 上午10:11:39
     * @param tableName
     * @return
     */@OverridepublicString createClass(String tableName){StringBuilder sb =newStringBuilder();String[] temps = tableName.split("_");
        tableName = temps[0];for(int i =1; i < temps.length; i++){
            tableName +=StringUtil.initialtoUpper(temps[i]);}
        sb.append("public class "+StringUtil.initialtoUpper(tableName)+" {<br>");return sb.toString();}/**
     * @Description 创建变量
     * @author zhangyd
     * @date 2015年12月9日 上午10:11:55
     * @param tableInfo
     * @return
     */@OverridepublicString createVariables(List<Variable> tableInfo){StringBuilder sb =newStringBuilder();for(Variable variable : tableInfo){if(StringUtil.isNotEmpty(variable.getComment())){
                sb.append(" //"+ variable.getComment()+"<br>");}
            sb.append(" private "+ dataTypeMapping.get(variable.getType())+" "+ variable.getPropertyNames()+";<br>");}
        sb.append("<br>");return sb.toString();}/**
     * @Description 创建set、get方法
     * @author zhangyd
     * @date 2015年12月9日 上午10:12:02
     * @param tableInfo
     * @return
     */@OverridepublicString createSetAndGet(List<Variable> tableInfo){StringBuilder sb =newStringBuilder();for(Variable variable : tableInfo){
            sb.append(" public void set"+StringUtil.initialtoUpper(variable.getPropertyNames())+"("+ dataTypeMapping.get(variable.getType())+" "+ variable.getPropertyNames()+"){<br>");
            sb.append("     this."+ variable.getPropertyNames()+" = "+ variable.getPropertyNames()+";<br>");
            sb.append(" }<br><br>");

            sb.append(" public "+ dataTypeMapping.get(variable.getType())+" get"+StringUtil.initialtoUpper(variable.getPropertyNames())+"(){<br>");
            sb.append("     return this."+ variable.getPropertyNames()+";<br>");
            sb.append(" }<br><br>");}return sb.toString();}/**
     * @Description 创建class尾部
     * @author zhangyd
     * @date 2015年12月9日 上午10:12:09
     * @return
     */@OverridepublicString createTail(){return"}";}}
  • 关于文件导出
/**
     * @Description 得到生成的实体字符串
     * @author zhangyd
     * @date 2015年12月9日 上午9:51:36 
     * @param sqlForm
     * @return
     */@RequestMapping(value ="/getJava", produces ="application/json; charset=utf-8")@ResponseBodypublicString getJava(TableForm sqlForm){try{String filename =StringUtil.splitAndtoUpper(sqlForm.getSelectedTableNames(),"_")+".java";String path = generationClassService.getSaveFilePath(filename, sqlForm);MemcachedUtil.set("java_path", path);MemcachedUtil.set("java_name", filename);}catch(Exception e){
            e.printStackTrace();}Map<String,Object> map = generationClassService.getJava(sqlForm);// 页面用,保证队形String sql =(String) map.get("list");
        map.put("list", sql.replace("   "," "));JSONObject jsonObject =JSONObject.fromObject(map);return jsonObject.toString();}
/**
     * @Description 获取保存文件的地址
     * @author zhangyd
     * @date 2015年12月18日 下午4:27:35
     * @param filename
     * @param mybatisSqlForm
     * @return
     */@OverridepublicString getSaveFilePath(String filename,TableForm mybatisSqlForm){
        filename =StringUtil.initialtoUpper(filename);Map<String,Object> map =this.getJava(mybatisSqlForm);String sql =(String) map.get("list");
        sql = sql.replace("<br>","\n");String path =FileUtil.getGenerationJavaFilePath()+ filename;FileUtil.saveFile(path, sql.replace("<br>","\n"));MemcachedUtil.set("java_path", path);return path;}

说明:因为我设计的是在点击生成java代码后才会显示导出按钮,因此,在生成java代码时就要把内容保存到文件中,供下载导出。同时,因为我没有用到数据库表记录生成的文件路径和名字,我用的是Memcache缓存,此处无强求,根据个人爱好,爱咋整咋整。

  • 将字符串保存到新文件中
/**
     * @Description 将字符串写入文件==生成文件
     * @author zhangyd
     * @date 2015年12月8日 下午3:29:49
     * @param filePath
     * @param content
     * @return
     */publicstaticboolean saveFile(String filePath,String content){return saveFile(filePath, content,"UTF-8");}/**
     * @Description 将字符串写入文件==生成文件
     * @author zhangyd
     * @date 2015年12月9日 下午1:32:30
     * @param path
     * @param content
     * @param encodeingType
     * @return
     */publicstaticboolean saveFile(String path,String content,String encodeingType){boolean flag =false;DataOutputStream dos =null;try{File file =newFile(path);if(content !=null&& content.length()>=0){byte abyte[]= content.getBytes(encodeingType);
                dos =newDataOutputStream(newFileOutputStream(file));
                dos.write(abyte,0, abyte.length);
                dos.flush();

                flag =true;}}catch(FileNotFoundException e){
            e.printStackTrace();}catch(IOException e){
            e.printStackTrace();}finally{if(dos !=null){
                close(dos);}}return flag;}

OK,到这儿就算到量了,基本的流程和逻辑以及核心代码,就是以上所示。如果感兴趣,可以根据这个思路自己弄一个。如果以上有看不明白的,或者我写的有不明确的地方,请随时call我,或者本文留言也行。

......
恭迎各位大神指点......

0
1
分享到:
评论
1 楼 white_crucifix 2015-12-21  
居然不把代码放在 code标签里

相关推荐

    自己写的springboot + mybatis plus + vue代码生成器

    干货分享,减少重复劳动,让工作更专注,为提高开发效率而出的代码生成器,支持mysql,sqlserver,oracle 等主流数据库,单表增删改查一键生成,大家可随意修改模版来满足你的需要。 运行环境 jdk8+ 项目技术 ...

    [干货][EMIT]千行代码实现代理式AOP+属性的自动装配

    【干货分享】代理式AOP(面向切面编程)与属性自动装配是现代软件开发中的重要技术,尤其在企业级应用开发中广泛使用。本文将通过千行代码的实例解析,帮助你深入理解并掌握这两种技术。AOP主要用于解决代码中的横切...

    springboot + mybatis plus + vue代码生成器

    干货分享,减少重复劳动,让工作更专注,为提高开发效率而出的代码生成器,支持mysql,sqlserver,oracle 等主流数据库,单表增删改查一键生成,大家可随意修改模版来满足你的需要。 运行环境 jdk8+ 项目技术...

    Android代码-干货集中营

    干货集中营 学习安卓的一款应用,每天更新技术文章下载APP 用到的技术 三级缓存 自定义控件:listview的下拉刷新,上拉加载更多 RecycleView与CardView结合实现瀑布流,下拉刷新,item点击事件 volley异步加载网络...

    点赞代码(干货)

    这篇“点赞代码(干货)”很可能是提供了一套实现点赞功能的源代码,旨在帮助开发者快速理解和构建自己的点赞系统。源码通常包含了实现特定功能的完整程序逻辑,对于初学者或有经验的开发者来说都是宝贵的学习资源。...

    通信工程专业认识实习报告干货2篇.doc

    通信工程专业认识实习报告干货 本文是一篇通信工程专业认识实习报告,旨在总结实习的收获和经验。报告中涵盖了实习目的、实习时间地点、实习内容、实习收获、以及未来的发展方向等。 一、实习目的 通过这次实习,...

    [干货][EMIT]千行代码实现代理式AOP+属性的自动装配 V2.0

    在方法调用前插入自己的代码(例如记录日志),然后调用原始方法,最后执行后置通知。 5. 对于属性的自动装配,通过反射获取属性信息,然后使用Emit生成IL代码,在构造函数或特定方法中设置属性值。 6. 实例化代理...

    2018美团技术干货(算法篇,后台篇,工程师成长篇,前端篇,测试篇,运维篇,系统篇)

    美团的技术干货可能涵盖了数据结构、排序算法、搜索算法、图论、机器学习算法等内容,如Dijkstra算法、KMP匹配、贪心策略、深度学习模型等,这些都是提升业务效率的关键。 2. **后台篇**:后台开发主要关注服务端...

    Android代码-干货搜索器,功能是搜索gank.io中的干货

    这是干货搜索器的第二个版本V2,因为@代码家提供了官方的干货搜索接口咯! 官方的干货搜索接口真是碾压一切啊!用起来相当方便,搜索结果也是非常丰富! 使用方式 下载最新版本的workflow文件双击使用Alfred打开即可...

    不止代码-阿里干货[超清彩色中文带目录版][PDF]

    《不止代码-阿里干货》是阿里集团发布的一本专门针对程序员职业发展的干货指南,它以超清彩色中文版的形式呈现,包含完整的目录结构,便于读者查阅。这本书旨在为程序员提供全面的职业规划指导,帮助他们在技术与...

    Android代码-安卓干货圈

    【Android代码-安卓干货圈】是一个专注于Android开发领域的资源库,包含了各种实用的代码示例、工具类、库以及开发者们在实践中积累的技巧和经验。这个资源集合旨在帮助Android开发者提升技能,解决实际问题,同时也...

    干货代码MATLAB控制CST进行建模仿真

    标题中的“干货代码MATLAB控制CST进行建模仿真”表明了这个压缩包内容的核心,即使用MATLAB编程控制CST(Computer Simulation Technology)软件进行电磁仿真。MATLAB是一款强大的数学计算软件,广泛用于数值分析、...

    POI干货(第一版代码 后续可以私聊我)

    标题 "POI干货(第一版代码 后续可以私聊我)" 提及的是与Apache POI相关的编程实践,这是一款流行的Java库,用于读写Microsoft Office格式的文件,如Excel、Word和PowerPoint。这个"第一版代码"很可能是作者提供的一...

    干货集中营微信小程序

    4. 在线投稿:用户可以直接在小程序内提交自己的原创内容或整理的干货,促进了知识的交流与传播。 5. 网络ID输入:用户可以通过输入自己的网络ID来建立个人品牌,提高自己的影响力,并与其他用户互动。 【微信小...

    干货标准超市干货.doc

    干货是食品市场中常见的一类商品,主要包括各种坚果、果实、菌菇、豆制品、调味料等,它们在保存和销售时需要遵循一定的标准以确保品质。以下是对这些干货产品的一些详细描述和优质劣质的区分标准: 1. 南瓜子:...

    Git学习笔记干货

    Git学习笔记干货 Git 是什么? Git 是目前世界上最先进的分布式版本控制系统。版本控制系统是指一种记录、跟踪和管理代码变动的系统。Git 的出现解决了手动管理多个“版本”的问题,使得多人协作编辑变得更加方便。...

    干货系列的源码,为了理解代码,注释比较多,代码不够简洁!如果想用于生产环境,我建议自己优化代码再使用

    10. **代码审查**:定期进行代码审查,让团队成员互相学习和发现潜在问题,提升整体代码质量。 在处理“ghcode-master”中的源码时,你可以按照以上步骤逐步进行优化。首先,理解每个类和方法的作用,然后对不必要...

    干货资料 贴片元件代码表.pdf

    总结来说,贴片元件代码表是电子工程师不可或缺的工具,它可以帮助工程师快速找到所需元件的详细信息,从而加快电路设计和故障排查的速度。开关电源设计中,对这些元件的认识和选择尤为关键,因为它们直接影响到开关...

    面试干货人工智能篇.pdf

    【面试干货】人工智能篇.pdf【面试干货】人工智能篇.pdf

    Flutter实现的干货集中营客户端.zip

    "Flutter实现的干货集中营客户端.zip"是一个开源项目,它使用Flutter框架构建了一个名为“干货集中营”的移动应用客户端。这个客户端可能是为了提供技术文章、教程或者行业资讯等内容,方便开发者们获取学习资料和...

Global site tag (gtag.js) - Google Analytics