当前位置: 首页 > 编程日记 > 正文

告别无止境的增删改查:Java代码生成器

对于一个比较大的业务系统,我们总是无止境的增加,删除,修改,粘贴,复制,想想总让人产生一种抗拒的心里。那有什么办法可以在正常的开发进度下自动生成一些类,配置文件,或者接口呢?

有感于马上要做个比较大的业务系统,想到那无止境的增删改查、粘贴复制,顿时脑后升起一阵凉风。于是想到个找或者写一个Java代码的生成器,这样在正常开发进度下,也能余下更多的时间去做些别的事情。

闲话少说,首先总结下需求:

我需要的这个工具能够读取数据库表结构,通过对字段类型、名称等分析得到需要的各种变量,根据模板生成相应的pojo类、hibernate的xml配置文件、dao和service的接口和类。

需求看起来很简单,但是一是没搞过这样的小工具,二是技术不过关,所以还是想到了找找有没有开源的代码拿过来根据自己的需求改。

于是找到了rapid-generator这个开源工具,同学们可以下载rapid-generator直接使用,根据自己的需求写好模板就行了。

由于自己项目中的特殊情况和公司规范等因素,另外也是想学习下别人的设计,所以我对源码进行了删减和功能的修改。

来看下主要的类:

Table:根据表结构建立的对象。

Column:根据表中每列建立的对象。

Generator:生成器核心类,主要负责根据表对象和读取FreeMarker模板生成最后的java代码文件。

GeneratorControl:控制生成过程等的一些参数,例如文件是否覆盖、文件编码等。

GeneratorProperties:读取配置文件的类,配置文件包括数据库连接信息和一些基本的参数配置。

下面来看一下模板的编写:

pojo模板:

  1. <#include "/java_copyright.include">  
  2. <#assign className = table.className>
  3. <#assign classNameLower = className?uncap_first>
  4. package ${basepackage}.pojo.${mpackage}.${table.classNameFirstLower};  
  5. <#include "/java_imports.include">  
  6. import com.linkage.agri.pojo.base.BaseEntity;  
  7. public class ${className} extends BaseEntity {  
  8. private static final long serialVersionUID = 5454155825314635342L;  
  9. <#list table.columns as column>
  10. /**  
  11.      * ${column.remarks}  
  12.      */ 
  13. private ${column.simpleJavaType} ${column.columnNameLower};  
  14. </#list>
  15. <@generateJavaColumns/>  
  16. <#macro generateJavaColumns>
  17. <#list table.columns as column>
  18. <#if column.isDateTimeColumn>  
  19. public String get${column.columnName}String() {  
  20. return DateConvertUtils.format(get${column.columnName}(), FORMAT_${column.constantName});  
  21. }
  22. public void set${column.columnName}String(String ${column.columnNameLower}) {  
  23. set${column.columnName}(DateConvertUtils.parse(${column.columnNameLower}, FORMAT_${column.constantName},${column.simpleJavaType}.class));  
  24. }
  25. </#if>      
  26. public void set${column.columnName}(${column.simpleJavaType} ${column.columnNameLower}) {  
  27. this.${column.columnNameLower} = ${column.columnNameLower};  
  28. }
  29. public ${column.simpleJavaType} get${column.columnName}() {  
  30. return this.${column.columnNameLower};  
  31. }
  32. </#list>
  33. </#macro>

FreeMarker的基本语法可以看下FreeMarker中文手册。

${}可以引用很多变量,这些变量包括:环境变量、table对象、配置变量等,这些变量都装在一个map里,如果自己有特殊需求,当然可以修改源码来装载更多的变量值。

注意:当变量为对象时,访问对象的属性是通过get方法来访问的。例如${table.classNameFirstLower},是引用 table对象的getNameFirstLower()方法,即使table对象中没有nameFirstLower这个属性也能够引用。

再看下我写的dao的模板:

  1. <#include "/java_copyright.include">  
  2. <#assign className = table.className>
  3. <#assign classNameLower = className?uncap_first>
  4. package ${basepackage}.dao.${mpackage}.${table.classNameFirstLower};  
  5. import java.math.BigDecimal;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8. import com.linkage.agri.dao.base.AbstractHibernateDAO;  
  9. import com.linkage.agri.exception.DAOException;  
  10. import ${basepackage}.pojo.${mpackage}.${classNameLower}.${className};  
  11. <#include "/java_imports.include">  
  12. public Class ${className}DAOImpl extends AbstractHibernateDAO implements ${className}DAO  
  13. {
  14. /**  
  15.      * <query all>  
  16.      * @param paramMap  
  17.      * @param orderMap  
  18.      * @param pageNum  
  19.      * @param pageSize  
  20.      * @return  
  21.      * @throws DAOException  
  22.      */ 
  23. @SuppressWarnings 
  24. public List<${className}> queryList${className}ByAttr(Map<String, Object> paramMap, Map<String, String> orderMap, int pageNum,  
  25. int pageSize)  
  26. throws DAOException  
  27. {
  28. return super.listInstances(${className}.class, paramMap, orderMap, pageNum, pageSize);  
  29. }
  30. /**  
  31.      *   
  32.      * <find one by id>  
  33.      * @param serial  
  34.      * @throws DAOException  
  35.      */ 
  36. public ${className} find${className}By${table.pkColumn.columnName}(${table.pkColumn.simpleJavaType} ${table.pkColumn.columnNameFirstLower})  
  37. throws DAOException  
  38. {
  39. return (${className})super.findById(${className}.class, ${table.pkColumn.columnNameFirstLower});  
  40. }
  41. /**  
  42.      *   
  43.      * <save one>  
  44.      * @param ${table.classNameFirstLower}  
  45.      * @throws DAOException  
  46.      */ 
  47. public ${table.pkColumn.simpleJavaType} save${className}(${className} ${table.classNameFirstLower})  
  48. throws DAOException  
  49. {
  50. return (${table.pkColumn.simpleJavaType})super.saveInstance(${table.classNameFirstLower});  
  51. }
  52. /**  
  53.      *   
  54.      * <update one>  
  55.      * @param ${table.classNameFirstLower}  
  56.      * @throws DAOException  
  57.      */ 
  58. public void update${className}(${className} ${table.classNameFirstLower})  
  59. throws DAOException  
  60. {
  61. super.updateInstance(${className});  
  62. }
  63. /**  
  64.      * <check one is have?>  
  65.      * @param paramMap  
  66.      * @return  
  67.      * @throws DAOException  
  68.      */ 
  69. public boolean check${className}IsHaveByAttr(Map<String, Object> paramMap)  
  70. throws DAOException  
  71. {
  72. StringBuffer sqlBuffer = new StringBuffer();  
  73. sqlBuffer.append("SELECT COUNT(*) FROM ${table.sqlName} T ");  
  74. sqlBuffer.append("WHERE T.${table.pkColumn.sqlName} = ? ");  
  75. BigDecimal big = (BigDecimal)super.findUniqueResultBySQLWithParams(sqlBuffer.toString(), paramMap.get("${table.pkColumn.columnNameFirstLower}"));  
  76. return big.intValue() > 0 ? false : true;  
  77. }
  78. /**  
  79.      * <update some>  
  80.      * @param ${table.classNameFirstLower}List  
  81.      * @return  
  82.      * @throws DAOException  
  83.      */ 
  84. public void update${className}Batch(List<${className}> ${table.classNameFirstLower}List)  
  85. throws DAOException  
  86. {
  87. super.updateBatchInstance(${table.classNameFirstLower}List);  
  88. }
  89. /**  
  90.      *   
  91.      * <delete one>  
  92.      * @param ${table.classNameFirstLower}  
  93.      * @throws DAOException  
  94.      */ 
  95. public void delete${className}(${className} ${table.classNameFirstLower})  
  96. throws DAOException  
  97. {
  98. super.deleteInstance(${table.classNameFirstLower});  
  99. }
  100. }

建立模板是能否解决自己问题的关键,在摸索出门道以后写模板变的十分简单。其实原理很简单,就是用一系列占位符来替换实际的变量值。

模板路径可以按照实际项目中的路径来拜访,生成器可以读取某个路径下所有模板进行生成,结果如下图:

接口和实现:

就说这么多吧,感兴趣的可以研究下这个工具的源码,也DIY出一套自己代码生成工具。不感兴趣的直接写模板就能用。

我只是走在路上,偶尔驻足观赏,偶尔回头看看。

转载于:https://www.cnblogs.com/firstdream/p/5475025.html

相关文章:

Maven国内源设置 - OSChina国内源失效了,别更新了

Maven国内源设置 - OSChina国内源失效了&#xff0c;别更新了 原文&#xff1a;http://blog.csdn.net/chwshuang/article/details/52198932 最近在写一个Spring4.x SpringMVCMybatis零配置的文章&#xff0c;使用的源配的是公司的私有仓库&#xff0c;但是为了让其他人能够通过…

如何使用Next.js创建动态的Rick and Morty Wiki Web App

Building web apps with dynamic APIs and server side rendering are a way to give people a great experience both with content and speed. How can we use Next.js to easily build those apps?使用动态API和服务器端渲染来构建Web应用程序是一种使人们在内容和速度上都…

安装部署Spark 1.x Standalone模式集群

Configuration spark-env.sh HADOOP_CONF_DIR/opt/data02/hadoop-2.6.0-cdh5.4.0/etc/hadoop JAVA_HOME/opt/modules/jdk1.7.0_67 SCALA_HOME/opt/modules/scala-2.10.4 ####################################################### #主节点 …

算法(3)简单四则运算

1.0 问题描述 实现10以内四则运算&#xff08;只包含数字&#xff0c;*/和小括号&#xff09; 2.0 问题分析 四则运算使用“后缀表达式”算法来计算&#xff0c;后缀表达式可以无需考虑运算符优先级&#xff0c;直接从左至右依次计算。问题分解成2部分&#xff0c;一是将“中…

调用短信接口,先var_dump()看数据类型是object需要json_decode(json_encode( $resp),true)转换成array...

返回的数据.先看类型,如果是object类型 先json_encode, 再json_decode,加true 转换成数组 $resp $c->execute($req); var_dump($resp); object(stdClass)#12 (2) { ["result"]> object(stdClass)#13 (3) { ["err_code"]> string(1) "0"…

nlp文本数据增强_如何使用Texthero为您的NLP项目准备基于文本的数据集

nlp文本数据增强Natural Language Processing (NLP) is one of the most important fields of study and research in today’s world. It has many applications in the business sector such as chatbots, sentiment analysis, and document classification.Preprocessing an…

R语言-基础解析

二、操作基础%%取余%/%整数除法(1)eigen(...)求解方阵的特征值和特征向量(2)solve(D,A)求解DXA(3)data<-list(...)取里面的对象data[["列名称"]]&#xff1b;data[[下标]]&#xff1b;data$列名称(4)unlist(列表对象)把列表对象转化为向量对象(5)names(数据框)读取…

算法(4)数据结构:堆

1.0 问题描述 实现数据结构&#xff1a;堆。 2.0 问题分析 堆一般使用数组来表示&#xff0c;其中某个节点下标i的两个子节点的下标为 2i1 和 2i2。堆是一棵完全二叉树。堆有3种基本操作&#xff1a;创建&#xff0c;插入&#xff0c;删除。这3种操作都需要通过“调整堆”的…

cookie 和session 的区别详解

转自 https://www.cnblogs.com/shiyangxt/archive/2008/10/07/1305506.html 这些都是基础知识&#xff0c;不过有必要做深入了解。先简单介绍一下。 二者的定义&#xff1a; 当你在浏览网站的时候&#xff0c;WEB 服务器会先送一小小资料放在你的计算机上&#xff0c;Cookie 会…

如何设置Java Spring Boot JWT授权和认证

In the past month, I had a chance to implement JWT auth for a side project. I have previously worked with JWT in Ruby on Rails, but this was my first time in Spring. 在过去的一个月中&#xff0c;我有机会为辅助项目实现JWT auth。 我以前曾在Ruby on Rails中使用…

算法(5)哈希表

1.0 问题描述 实现数据结构&#xff1a;哈希表。 2.0 问题分析 哈希表可以看作我们经常使用的字典&#xff08;swift&#xff09;或对象&#xff08;js&#xff09;&#xff0c;可以让一个key&value对一一对应&#xff0c;可以快速根据key找到value。哈希表内部使用数组…

《面向对象程序设计》c++第五次作业___calculator plus plus

c第五次作业 Calculator plusplus 代码传送门 PS:这次作业仍然orz感谢一位同学与一位学长的windows帮助&#xff0c;同时再次吐槽作业对Mac系统用户的不友好。&#xff08;没朋友千万别用Mac&#xff01;&#xff01;&#xff01;&#xff09; 还有想吐槽作业对规范的要求大大超…

联合体union和大小端(big-endian、little-endian)

1.联合体union的基本特性——和struct的同与不同union&#xff0c;中文名“联合体、共用体”&#xff0c;在某种程度上类似结构体struct的一种数据结构&#xff0c;共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。在成员完全相同的情况下&#xff0c;struct比…

前端面试的作品示例_如何回答任何技术面试问题-包括示例

前端面试的作品示例Technical interviews can be extremely daunting. From the beginning of each question to the end, its important to know what to expect, and to be aware of the areas you might be asked about. 技术面试可能会非常艰巨。 从每个问题的开始到结束&a…

$(shell expr $(MAKE_VERSION) \= 3.81) 这里“\”的解释

android/build/core/main.mk $(shell expr $(MAKE_VERSION) \> 3.81) 为什么要加多一个“\”,因为">"会被shell解析为重定向符号&#xff0c;所以需要转义或用引号包围 所以&#xff0c;也可以这样写$(shell expr $(MAKE_VERSION) “>” 3.81)转载于:https:…

iOS应用模块化的思考及落地方案(一)模块的划分及模块化工作流程

1.0 什么是模块化 很多关于重构及设计模式的介绍中&#xff0c;经常提到的几个词语是复用及解耦。 模块化之所以被提出&#xff0c;也更多是为了解决这几个问题。 复用可以减少重复造轮子的情况&#xff0c;很容易理解的是&#xff0c;我们经常使用的github上的第三方框架&a…

Swiper 用法

部分常用API ininialSlide: 2, //起始图片切换的索引位置&#xff08;起始从0开始&#xff0c;默认为0&#xff09; autoplay: 3000, //设置自动切换时间&#xff0c;单位毫秒 speed: 1000, //设置滑动速度 continuous: true, //无限循环的图片切换效果 disableScroll: true, /…

node/js 漏洞_6个可用于检查Node.js中漏洞的工具

node/js 漏洞Vulnerabilities can exist in all products. The larger your software grows, the greater the potential for vulnerabilities. 所有产品中都可能存在漏洞。 您的软件增长得越大&#xff0c;潜在的漏洞就越大。 Vulnerabilities create opportunities for expl…

发现一个浏览器很奇怪的问题

浏览器有8个请求状态为pending时&#xff0c;在另一个tab中&#xff0c;请求就发布出去了&#xff0c;一直是stalled。直到pending状态变成了cancled状态。 试了360浏览器&#xff08;谷歌内核&#xff09;和chrome浏览器&#xff0c;都是这样。 具体的原因待深究 参考&#xf…

wamp配置虚拟主机

因为wampserver的php版本一直是5.x版本&#xff1b;因此转投xmapp用了一段时间&#xff1b; 意外发现wampserver3更新了&#xff1b;php也终于更新到7了&#xff1b; 果断还是决定回到wampserver的怀抱&#xff1b; 然后有意外的发现了wampserver3有了新功能&#xff1b;可以方…

iOS应用模块化的思考及落地方案(二)模块化自动构建工具的使用

1.0 iOS模块化中的问题 前文已经介绍了模块化的流程及一些常见的问题&#xff0c;我们在这里再次总结一下。 在工作中&#xff0c;当我们开始一个新项目的时候&#xff0c;最先考虑的就是模块化工作。 模块化工作的想法是很美好的&#xff0c;可是执行过程中会遇到很多的问题…

aws fargate_我如何在AWS Fargate上部署#100DaysOfCloud Twitter Bot

aws fargateAfter passing my last certification, I asked myself how much time I spent studying cloud computing.通过上一份认证后&#xff0c;我问自己自己花了多少时间研究云计算。 More than 100 days!超过100天&#xff01; It also made me realize two things:这也…

think in Java 第五章之垃圾回收类型

1.引用计数&#xff1a; 每个对象都含有一个引用计数器&#xff0c;当有引用连接至对象时&#xff0c;引用计数加1&#xff0c;当引用离开作用域或被置为null时&#xff0c;引用计数减1. 缺陷&#xff1a;在对象循环引用时&#xff0c;存在“对象应该被回收&#xff0c;引用计数…

Yii 错误页面处理

【错误页面处理】 訪问一个错误的控制器 訪问一个错误的方法 有些控制器和方法禁止訪问 以上訪问会提示错误信息 404 403 以上错误信息是不方便给外边用户看到的。 1. 安全隐患 2. 用户体验不好 错误信息在site/error这个地方定义的。如今我们要自己定义错误页面来显示我们的错…

设置RGBColor

#define kUIColorFromRGB(rgbValue) [UIColor \colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

自学成才翁_作为一名自学成才的开发者从“我的旅程”中吸取的教训

自学成才翁The path of the self-taught developer is tough and filled with uncertainty. There is no straight line from newbie to career programmer. Because of this, I believe all self-taught developers have a unique story to tell.自学成才的开发者之路艰难而充…

67)vector的begin() end() 和 front() back()的区别 rbegin() rend()

1&#xff09; 2&#xff09;v1.begin() 和v1.end&#xff08;&#xff09; 是作为迭代器v1的 第一个位置 和 最后一个元素的下一个位置。 v1.front() 是v1这个动态数组的第一个元素的值 v1.back()是v1的最后一个元素的值。 3&#xff09; 4&#xff09;正向和反向的使…

倒置函数reverse的用法

倒置字符串函数reverse&#xff1a;用于倒置字符串s中的各个字符的位置&#xff0c;如原来字符串中如果初始值为123456&#xff0c;则通过reverse函数可将其倒置为654321&#xff0c;程序如下&#xff1a;#include<stdio.h>#include<string.h>void reverse(char s[…

设置tabbaritem的title的颜色及按钮图片

设置title颜色&#xff1a; [[UITabBarItem appearance] setTitleTextAttributes:{NSForegroundColorAttributeName : kUIColorFromRGB(0xb2151c)} forState:UIControlStateSelected]; 设置按钮图片&#xff1a; UIImage *commonImage [UIImage imageNamed:[NSString strin…

helm部署仓库中没有的包_Kubernetes的Helm软件包管理器简介

helm部署仓库中没有的包Before we dive into the Helm package manager, Im going to explain some key concepts to deploying any application anywhere. Ill also give you a brief introduction to Kubernetes terminology.在深入研究Helm软件包管理器之前 &#xff0c;我将…