需求:
1. 当设计好数据库之后能够一键生成一些重复的代码,光是CRUD都能省很多时间,让咱们程序员只负责业务岂不快哉。所以生成器需要能生成常用的增删改查
2.项目过程中很有可能会修改表字段,除非前期工作做得非常好,有人创建表的时候会预留一些字段,但是我的习惯是 这些字段只有项目已经上线之后才使用
实现流程:
一、 准备工作
1. idea 其实eclipse也可以 无所谓
2.maven 因为需要打成jar包,maven比较简单,用jdk打包也行 无所谓
3.数据库驱动包
4.项目结构图如下
二、pom和模板 因为使用模板替换的,没有使用第三方模板,就自己定义字符串来搞的,反正也不复杂,难得用第三方的了
1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.cms</groupId>
<artifactId>cms</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerVersion>1.8</compilerVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. 模板类
package com.cms.template;
public class Template {
/**
* 父级模型模板
*/
public static final String CLASS_BASE_TEMPLATE = "package {{baseModelPackage}};\n" +
"import java.io.Serializable;\n" +
"{{imports}}" +
"public class {{classname}}Base implements Serializable{\n" +
"\tprivate static final long serialVersionUID = 1L;\n"+
"{{fields}}" +
"{{getter_setter}}" +
"}";
/**
* 子级模型模板
*/
public static final String CLASS_TEMPLATE = "package {{modelPackage}};\n" +
"import {{baseModelPackage}}.{{classname}}Base;\n" +
"public class {{classname}} extends {{classname}}Base{\n" +
"\tprivate static final long serialVersionUID = 1L;\n"+
"}";
/**
* 父级DAO
*/
public static final String BASE_DAO_TEMPLATE = "package {{baseDAOPackage}};\n" +
"import java.util.List;\n" +
"import org.apache.ibatis.annotations.Param;\n" +
"import {{modelPackage}}.{{classname}};\n" +
"public interface {{classname}}BaseDAO{\n" +
"\tint insert({{classname}} obj);\n"+
"\tint updateById({{classname}} obj);\n"+
"\tint deleteById(Long id);\n"+
"\t{{classname}} selectOneById(@Param(\"id\")Long id,@Param(\"logicWhereSql\")String logicWhereSql);\n"+
"\tList<{{classname}}> selectAll(String logicWhereSql);\n"+
"}";
/**
* 子级DAO
*/
public static final String DAO_TEMPLATE = "package {{daoPackage}};\n" +
"import java.util.List;\n" +
"import org.apache.ibatis.annotations.Param;\n" +
"import {{modelPackage}}.{{classname}};\n" +
"import {{pageDTOPackage}}.{{classname}}PageDTO;\n" +
"import {{baseDAOPackage}}.{{classname}}BaseDAO;\n" +
"public interface {{classname}}DAO extends {{classname}}BaseDAO{\n" +
"\tint logicDeleteById(@Param(\"id\")Long id,@Param(\"logicSetSql\")String logicSetSql);\n"+
"\tlong selectCount(@Param(\"dto\"){{classname}}PageDTO dto,@Param(\"logicWhereSql\")String logicWhereSql);\n"+
"\tList<{{classname}}> selectPage(@Param(\"dto\"){{classname}}PageDTO dto,@Param(\"logicWhereSql\")String logicWhereSql);\n"+
"}";
/**
* Service
*/
public static final String SERVICE_TEMPLATE = "package {{servicePackage}};\n" +
"import org.springframework.beans.factory.annotation.Autowired;\n" +
"import org.springframework.stereotype.Service;\n" +
"import org.springframework.transaction.annotation.Transactional;\n" +
"import {{modelPackage}}.{{classname}};\n" +
"import {{pageDTOPackage}}.{{classname}}PageDTO;\n" +
"import {{daoPackage}}.{{classname}}DAO;\n" +
"import {{resultDTOPackage}}.{{resultDTO}};\n" +
"@Service\n" +
"public class {{classname}}Service{\n" +
"\tprivate static final String logicWhereSql=\"deleted = 1\";\n"+
"\tprivate static final String logicSetSql=\"set deleted = -1\";\n"+
"\t@Autowired\n" +
"\tprivate {{classname}}DAO {{class_var}}DAO;\n" +
"\tprivate String validate({{classname}} obj){return null;}\n"+
"\t@Transactional\n"+
"\tpublic {{resultDTO}} insert({{classname}} obj){\n"+
"\t\tString validateResult = validate(obj);\n"+
"\t\tif(validateResult!=null&&validateResult.length()!=0){\n" +
"\t\t\treturn {{resultDTO}}.put400(validateResult,\"params validate failed.\");\n"+
"\t\t}\n"+
"\t\ttry {\n"+
"\t\t\t{{class_var}}DAO.insert(obj);\n"+
"\t\t\treturn {{resultDTO}}.putSuccess(\"ok\");\n"+
"\t\t}catch(Exception e){\n" +
"\t\t\treturn {{resultDTO}}.put500(\"insert {{classname}} failed\",e.getMessage());\n"+
"\t\t}\n"+
"\t}\n"+
"\t@Transactional\n"+
"\tpublic {{resultDTO}} updateById({{classname}} obj){\n"+
"\t\tString validateResult = validate(obj);\n"+
"\t\tif(validateResult!=null&&validateResult.length()!=0){\n" +
"\t\t\treturn {{resultDTO}}.put400(validateResult,\"params validate failed.\");\n"+
"\t\t}\n"+
"\t\ttry {\n"+
"\t\t\t{{class_var}}DAO.updateById(obj);\n"+
"\t\t\treturn {{resultDTO}}.putSuccess(\"ok\");\n"+
"\t\t}catch(Exception e){\n" +
"\t\t\treturn {{resultDTO}}.put500(\"update {{classname}} failed\",e.getMessage());\n"+
"\t\t}\n"+
"\t}\n"+
"\t@Transactional\n"+
"\tpublic {{resultDTO}} deleteById(Long id){\n"+
"\t\ttry {\n"+
"\t\t\t{{class_var}}DAO.deleteById(id);\n"+
"\t\t\treturn {{resultDTO}}.putSuccess(\"ok\");\n"+
"\t\t}catch(Exception e){\n" +
"\t\t\treturn {{resultDTO}}.put500(\"delete {{classname}} failed\",e.getMessage());\n"+
"\t\t}\n"+
"\t}\n"+
"\t@Transactional\n"+
"\tpublic {{resultDTO}} logicDeleteById(Long id){\n"+
"\t\ttry {\n"+
"\t\t\t{{class_var}}DAO.logicDeleteById(id,logicSetSql);\n"+
"\t\t\treturn {{resultDTO}}.putSuccess(\"ok\");\n"+
"\t\t}catch(Exception e){\n" +
"\t\t\treturn {{resultDTO}}.put500(\"delete {{classname}} failed\",e.getMessage());\n"+
"\t\t}\n"+
"\t}\n"+
"\tpublic {{resultDTO}} selectOneById(Long id){\n"+
"\t\ttry {\n"+
"\t\t\treturn {{resultDTO}}.putSuccess(\"ok\",{{class_var}}DAO.selectOneById(id,logicWhereSql));\n"+
"\t\t}catch(Exception e){\n" +
"\t\t\treturn {{resultDTO}}.put500(\"query one {{classname}} failed\",e.getMessage());\n"+
"\t\t}\n"+
"\t}\n"+
"\tpublic {{resultDTO}} selectAll(){\n"+
"\t\ttry {\n"+
"\t\t\treturn {{resultDTO}}.putSuccess(\"ok\",{{class_var}}DAO.selectAll(logicWhereSql));\n"+
"\t\t}catch(Exception e){\n" +
"\t\t\treturn {{resultDTO}}.put500(\"query all {{classname}} failed\",e.getMessage());\n"+
"\t\t}\n"+
"\t}\n"+
"\tpublic {{resultDTO}} paging({{classname}}PageDTO dto){\n"+
"\t\ttry {\n"+
"\t\t\tlong count = {{class_var}}DAO.selectCount(dto,logicWhereSql);\n"+
"\t\t\tdto.setTotal(count);\n"+
"\t\t\tif(count==0){\n" +
"\t\t\t\treturn {{resultDTO}}.putSuccess(\"ok\",dto);\n"+
"\t\t\t}\n"+
"\t\t\tdto.setData({{class_var}}DAO.selectPage(dto,logicWhereSql));\n"+
"\t\t\treturn {{resultDTO}}.putSuccess(\"ok\",dto);\n"+
"\t\t}catch(Exception e){\n" +
"\t\t\treturn {{resultDTO}}.put500(\"paging {{classname}} failed\",e.getMessage());\n"+
"\t\t}\n"+
"\t}\n"+
"}";
public static final String ACTION_TEMPLATE = "package {{actionPackage}};\n"+
"import org.springframework.stereotype.Controller;\n"+
"import org.springframework.web.bind.annotation.CrossOrigin;\n"+
"import org.springframework.web.bind.annotation.RequestMapping;\n"+
"import org.springframework.beans.factory.annotation.Autowired;\n" +
"import org.springframework.web.bind.annotation.RequestBody;\n"+
"import org.springframework.web.bind.annotation.ResponseBody;\n"+
"import {{servicePackage}}.{{classname}}Service;\n" +
"import {{modelPackage}}.{{classname}};\n" +
"import {{pageDTOPackage}}.{{classname}}PageDTO;\n" +
"import {{resultDTOPackage}}.{{resultDTO}};\n" +
"@Controller\n"+
"@RequestMapping(\"/{{class-mapping}}\")\n"+
"@CrossOrigin\n"+
"public class {{classname}}Action{\n"+
"\t@Autowired\n" +
"\tprivate {{classname}}Service {{class_var}}Service;\n" +
"\t@RequestMapping(\"/add\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} add(@RequestBody {{classname}} obj) {\n"+
"\t\treturn {{class_var}}Service.insert(obj);\n"+
"\t}\n"+
"\t@RequestMapping(\"/edit\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} edit(@RequestBody {{classname}} obj) {\n"+
"\t\treturn {{class_var}}Service.updateById(obj);\n"+
"\t}\n"+
"\t@RequestMapping(\"/delete\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} delete(Long id) {\n"+
"\t\treturn {{class_var}}Service.deleteById(id);\n"+
"\t}\n"+
"\t@RequestMapping(\"/delete-logic\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} deleteLogic(Long id) {\n"+
"\t\treturn {{class_var}}Service.logicDeleteById(id);\n"+
"\t}\n"+
"\t@RequestMapping(\"/selectOne\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} selectOne(Long id) {\n"+
"\t\treturn {{class_var}}Service.selectOneById(id);\n"+
"\t}\n"+
"\t@RequestMapping(\"/selectAll\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} selectAll() {\n"+
"\t\treturn {{class_var}}Service.selectAll();\n"+
"\t}\n"+
"\t@RequestMapping(\"/paging\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} paging(@RequestBody {{classname}}PageDTO dto) {\n"+
"\t\treturn {{class_var}}Service.paging(dto);\n"+
"\t}\n"+
"}";
public static final String API_ACTION_TEMPLATE = "package {{apiActionPackage}};\n"+
"import org.springframework.stereotype.Controller;\n"+
"import org.springframework.web.bind.annotation.CrossOrigin;\n"+
"import org.springframework.web.bind.annotation.RequestMapping;\n"+
"import org.springframework.beans.factory.annotation.Autowired;\n" +
"import org.springframework.web.bind.annotation.RequestBody;\n"+
"import org.springframework.web.bind.annotation.ResponseBody;\n"+
"import {{servicePackage}}.{{classname}}Service;\n" +
"import {{modelPackage}}.{{classname}};\n" +
"import {{pageDTOPackage}}.{{classname}}PageDTO;\n" +
"import {{resultDTOPackage}}.{{resultDTO}};\n" +
"@Controller\n"+
"@RequestMapping(\"/api/{{class-mapping}}\")\n"+
"@CrossOrigin\n"+
"public class API{{classname}}Action{\n"+
"\t@Autowired\n" +
"\tprivate {{classname}}Service {{class_var}}Service;\n" +
"\t@RequestMapping(\"/add\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} add(@RequestBody {{classname}} obj) {\n"+
"\t\treturn {{class_var}}Service.insert(obj);\n"+
"\t}\n"+
"\t@RequestMapping(\"/edit\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} edit(@RequestBody {{classname}} obj) {\n"+
"\t\treturn {{class_var}}Service.updateById(obj);\n"+
"\t}\n"+
"\t@RequestMapping(\"/delete\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} delete(Long id) {\n"+
"\t\treturn {{class_var}}Service.deleteById(id);\n"+
"\t}\n"+
"\t@RequestMapping(\"/delete-logic\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} deleteLogic(Long id) {\n"+
"\t\treturn {{class_var}}Service.logicDeleteById(id);\n"+
"\t}\n"+
"\t@RequestMapping(\"/selectOne\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} selectOne(Long id) {\n"+
"\t\treturn {{class_var}}Service.selectOneById(id);\n"+
"\t}\n"+
"\t@RequestMapping(\"/selectAll\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} selectAll() {\n"+
"\t\treturn {{class_var}}Service.selectAll();\n"+
"\t}\n"+
"\t@RequestMapping(\"/paging\")\n"+
"\t@ResponseBody\n"+
"\tpublic {{resultDTO}} paging(@RequestBody {{classname}}PageDTO dto) {\n"+
"\t\treturn {{class_var}}Service.paging(dto);\n"+
"\t}\n"+
"}";
public static final String PAGE_DTO_TEMPLATE = "package {{pageDTOPackage}};\n"+
"import {{modelPackage}}.{{classname}};\n"+
"import {{pageDTOPackage}}.{{classname}}PageDTO;\n" +
"public class {{classname}}PageDTO extends {{pageDTO}}<{{classname}}>{\n"+
"}";
public static final String BASE_MAPPER_TEMPLATE = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n" +
"<mapper namespace=\"{{baseDAOPackage}}.{{classname}}BaseDAO\">\n" +
"\t<insert id=\"insert\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n" +
"\t\tinsert into `{{tableName}}`\n" +
"\t\t<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\" >\n"+
"{{into}}"+
"\t\t</trim>\n"+
"\t\t<trim prefix=\"VALUES (\" suffix=\");\" suffixOverrides=\",\" >\n" +
"{{values}}"+
"\t\t</trim>\n"+
"\t</insert>\n" +
"\t<update id=\"updateById\">\n" +
"\t\tupdate `{{tableName}}`\n"+
"\t\t<set>\n"+
"{{sets}}"+
"\t\t</set>\n"+
"\t\twhere id = #{id}\n"+
"\t</update>\n" +
"\t<delete id=\"deleteById\">\n" +
"\t\tdelete from `{{tableName}}` where id = #{id}\n"+
"\t</delete>\n" +
"\t<select id=\"selectOneById\" resultType=\"{{classname}}\">\n" +
"\t\tselect * from `{{tableName}}` where id = #{id}\n" +
"\t\t<if test=\"logicWhereSql!=null and logicWhereSql!=''\">\n\t\t\tand ${logicWhereSql}\n\t\t</if>\n"+
"\t</select>\n" +
"\t<select id=\"selectAll\" resultType=\"{{classname}}\">\n" +
"\t\tselect * from `{{tableName}}`\n" +
"\t\t<where>\n"+
"\t\t\t<if test=\"logicWhereSql!=null and logicWhereSql!=''\">\n\t\t\t\t${logicWhereSql}\n\t\t\t</if>\n"+
"\t\t</where>\n"+
"\t\torder by id desc\n"+
"\t</select>\n" +
"</mapper>";
public static final String MAPPER_TEMPLATE = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n" +
"<mapper namespace=\"{{daoPackage}}.{{classname}}DAO\">\n" +
"\t<update id=\"logicDeleteById\">\n" +
"\t\t<if test=\"logicSetSql!=ull and logicSetSql!=''\">\n"+
"\t\t\tupdate `{{tableName}}` ${logicSetSql} where id = #{id}\n"+
"\t\t</if>\n"+
"\t</update>\n" +
"\t<select id=\"selectCount\" resultType=\"long\">\n" +
"\t\tselect count(id) from `{{tableName}}` <include refid=\"whereSql\"></include>\n" +
"\t</select>\n" +
"\t<select id=\"selectPage\" resultType=\"{{classname}}\">\n" +
"\t\tselect * from `{{tableName}}` <include refid=\"whereSql\"></include> order by id desc LIMIT ${dto.fromRowIndex},${dto.pageSize}\n" +
"\t</select>\n" +
"\t<sql id=\"whereSql\">\n" +
"\t\t<where>\n"+
"\t\t\t<if test=\"logicWhereSql!=null and logicWhereSql!=''\">\n\t\t\t\t${logicWhereSql}\n\t\t\t</if>\n"+
"\t\t</where>\n"+
"\t</sql>\n" +
"</mapper>";
}
三、 包装类和工具类
1. 包装类 看名字就知道是 数据库类型转换为java类型的
package com.cms.dto;
public class DBType2JavaTypeDTO {
private String classname;//全限定名
private String name;//简写类名
private Class clz;//字节码
public DBType2JavaTypeDTO(String classname, String name, Class clz) {
this.classname = classname;
this.name = name;
this.clz = clz;
}
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Class getClz() {
return clz;
}
public void setClz(Class clz) {
this.clz = clz;
}
}
2. 工具类
1) ClassesUtil 这个类的作用就是转换类型,生成getter/setter和写文件的 方法上都有注释是干嘛的
package com.cms.util;
import com.cms.dto.DBType2JavaTypeDTO;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
public class ClassesUtil {
/**
* 表明->类名
*
* @param tableName 表名
* @param separator 分隔符 表的连接符,表名->类名时会将此连接符删除,并使用驼峰将前后进行拼接 如 dic_item --> DicItem
* @return
*/
public static String convertClassNameByTableName(String tableName, String separator) {
List<String> classes = new ArrayList<>();
//处理连接器
String newSeparator = separator==null?" ":separator;
String[] names = tableName.split(newSeparator);
String classname = "";
for (String str : names) {
classname += StringUtil.toFirstUpperCase(str);
}
return classname;
}
private static DBType2JavaTypeDTO convertJAVATypeByDBType(String dbType) {
dbType = dbType.toUpperCase();
switch(dbType){
case "VARCHAR":
case "TEXT":
case "CHAR":
return class2DTO(String.class);
case "DECIMAL":
return class2DTO(BigDecimal.class);
case "TINYINT":
case "SMALLINT":
case "MEDIUMINT":
case "INT":
return class2DTO(Integer.class);
case "BIGINT":
case "INTEGER":
return class2DTO(Long.class);
case "DATETIME":
case "TIMESTAMP":
case "DATE":
case "TIME":
return class2DTO(Date.class);
case "DOUBLE":
return class2DTO(Double.class);
case "FLOAT":
return class2DTO(Float.class);
case "BIT":
return class2DTO(Boolean.class);
}
return null;
}
/**
* class转模型
* @param clz
* @return
*/
private static DBType2JavaTypeDTO class2DTO(Class<?> clz){
return new DBType2JavaTypeDTO(clz.getName(),clz.getSimpleName(),clz);
}
/**
* 是否是不用导包的类型
* @return
*/
public static boolean isJAVALangType(Class<?> clz){
return short.class.equals(clz)||
byte.class.equals(clz)||
int.class.equals(clz)||
long.class.equals(clz)||
float.class.equals(clz)||
double.class.equals(clz)||
boolean.class.equals(clz)||
char.class.equals(clz)||
Integer.class.equals(clz)||
Long.class.equals(clz)||
Float.class.equals(clz)||
Double.class.equals(clz)||
String.class.equals(clz)||
Short.class.equals(clz)||
Byte.class.equals(clz)||
Character.class.equals(clz)||
Boolean.class.equals(clz);
}
/**
* 传入一个数据库类型字符串 返回一句导包代码
* @param clz
* @return
*/
public static String handlerImport(String clz){
DBType2JavaTypeDTO typeDTO = convertJAVATypeByDBType(clz);
if(!isJAVALangType(typeDTO.getClz())){
return "import\t"+typeDTO.getClassname()+";";
}
return "";
}
/**
* 根据变量名 数据库类型 和注释 返回一句字段+注释的代码
* @param type
* @param comment
* @return
*/
public static String handlerField(String name,String type, String comment) {
DBType2JavaTypeDTO typeDTO = convertJAVATypeByDBType(type);
if(StringUtil.isNotEmptyOrNull(comment)){
comment = "//"+comment;
}
return "\tprivate\t"+typeDTO.getName()+"\t"+name+";\t"+comment;
}
/**
* 生成getter/setter
* @param name
* @param type
* @return
*/
public static String handlerGetterAndSetter(String name, String type) {
DBType2JavaTypeDTO typeDTO = convertJAVATypeByDBType(type);
return "\tpublic "+typeDTO.getName()+" "+getter(name)+"(){\n"+
"\t\treturn this."+name+";\n"+
"\t}\n"+
"\tpublic void "+setter(name)+"("+typeDTO.getName()+" "+name+"){\n"+
"\t\tthis."+name+"="+name+";\n"+
"\t}";
}
/**
* 根据字段名生成set属性名
* @param name
* @return
*/
public static String setter(String name) {
String one = name.substring(0, 1);
String two = name.substring(1,2);
//如果第一个字符和第二个字符都是小写 就将第一个转大写
//如果第一个小写 第二个大写 不变
//如果第一个大写 不变
//所有只判断第一个和第二个是小写 其他都不变
int i = one.charAt(0);
int j = two.charAt(0);
if (i >= 97 && i <=122&&j >= 97 && j <=122){
one = one.toUpperCase();
return "set"+one+name.substring(1);
}else {
return "set"+name;
}
}
/**
* 根据字段名生成get属性名
* @param name
* @return
*/
public static String getter(String name) {
String one = name.substring(0, 1);
String two = name.substring(1,2);
//如果第一个字符和第二个字符都是小写 就将第一个转大写
//如果第一个小写 第二个大写 不变
//如果第一个大写 不变
//所有只判断第一个和第二个是小写 其他都不变
int i = one.charAt(0);
int j = two.charAt(0);
if (i >= 97 && i <=122&&j >= 97 && j <=122){
one = one.toUpperCase();
return "get"+one+name.substring(1);
}else {
return "get"+name;
}
}
/**
* 写文件
* @param rules
* @param packageStr
*/
private static String content = "";
public static void write(Map<String, String> rules, String packageStr,String filename,String template) {
content = template;
Set<Map.Entry<String, String>> entries = rules.entrySet();
for(Map.Entry<String, String> item:entries){
if(item.getValue()==null){
continue;
}
content = content.replace(item .getKey(),item.getValue());
}
String path = packageStr.replace(".", "/");
String url = Thread.currentThread().getContextClassLoader().getResource(".").getPath();
path = new File(url).getParentFile().getParentFile().toPath()+"/src/main/java/"+path+"/"+filename;
File file = new File(path);
//不存在
if (!file.exists()) {
file.getParentFile().mkdirs();
}
try {
FileOutputStream out = new FileOutputStream(file);
out.write(content.getBytes());
out.close();
System.out.println("文件写成功:"+path);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2)DBUtil 操作数据库相关的工具类
package com.cms.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DBUtil {
/**
* 获取链接对象
*/
public static Connection getConn(String url, String username, String password) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取当前使用的数据库名
*/
public static String getDatabaseName(Connection conn) {
try {
String sql = "select database();";
PreparedStatement state = conn.prepareStatement(sql);
ResultSet set = state.executeQuery();
if(set.next()) {
return set.getString("database()");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取所有表名
*/
public static List<String> getTables(Connection conn) {
List<String> list = new ArrayList<>();
try {
String sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=?";
PreparedStatement state = conn.prepareStatement(sql);
state.setObject(1,getDatabaseName(conn));
ResultSet query = state.executeQuery();
while(query.next()){
list.add(query.getString("TABLE_NAME"));
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 获取某表的字段名
* @return
*/
public static List<Map<String,String>> getTableInfo(Connection conn,String tableName){
List<Map<String,String>> list = new ArrayList<>();
try {
String sql = "SELECT COLUMN_NAME,COLUMN_KEY,DATA_TYPE,COLUMN_COMMENT FROM `information_schema`.`columns`" +
"WHERE `table_schema` = ?" + "AND `table_name` = ?;";
PreparedStatement state = conn.prepareStatement(sql);
state.setObject(1, getDatabaseName(conn));
state.setObject(2, tableName);
ResultSet query = state.executeQuery();
while(query.next()){
Map<String,String> map = new HashMap<>();
map.put("name",query.getString("COLUMN_NAME"));
map.put("type",query.getString("DATA_TYPE"));
map.put("comment",query.getString("COLUMN_COMMENT"));
list.add(map);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
3. StringUtil 字符串相关工具类
package com.cms.util;
public class StringUtil {
public static boolean isEmptyOrNull(String str){
return str==null||"".equals(str.trim());
}
public static boolean isNotEmptyOrNull(String str){
return str!=null&&!"".equals(str.trim());
}
/**
* 首字母大写
* @param str
* @return
*/
public static String toFirstUpperCase(String str){
if(isEmptyOrNull(str)){
return "";
}
char[] cs=str.toCharArray();
if(cs[0]>=95){
cs[0]-=32;
}
return String.valueOf(cs);
}
/**
* 首字母小写
* @param str
* @return
*/
public static String toFirstLowerCase(String str){
char[] cs=str.toCharArray();
if(cs[0]<95){
cs[0]+=32;
}
return String.valueOf(cs);
}
}
4. TemplateUtil 这个就是替换模板的工具类 也就是把模板换成需要的代码的 只有一个方法
package com.cms.util;
import java.sql.Connection;
import java.util.*;
public class TemplateUtil {
public static Map<String,String> handlerRules(Connection connection, String tableName, String separator,
String baseModelPackage, String modelPackage,
String baseDAOPackage, String daoPackage,
String baseMapperPackage, String mapperPackage,
String servicePackage, String actionPackage,
String apiActionPackage, String pageDTOPackage,
String pageDTO,String resultDTO,String resultDTOPackage){
String classname = ClassesUtil.convertClassNameByTableName(tableName, separator);
Map<String,String> rules = new HashMap<>();
rules.put("{{tableName}}",tableName);
rules.put("{{baseModelPackage}}",baseModelPackage);
rules.put("{{modelPackage}}",modelPackage);
rules.put("{{baseDAOPackage}}",baseDAOPackage);
rules.put("{{daoPackage}}",daoPackage);
rules.put("{{baseMapperPackage}}",baseMapperPackage);
rules.put("{{mapperPackage}}",mapperPackage);
rules.put("{{servicePackage}}",servicePackage);
rules.put("{{actionPackage}}",actionPackage);
rules.put("{{apiActionPackage}}",apiActionPackage);
rules.put("{{pageDTOPackage}}",pageDTOPackage);
rules.put("{{pageDTO}}",pageDTO);
rules.put("{{classname}}",classname);
rules.put("{{resultDTO}}",resultDTO);
rules.put("{{resultDTOPackage}}",resultDTOPackage);
rules.put("{{class-mapping}}",tableName.replace(separator,"-"));
//类名转变量名
rules.put("{{class_var}}",StringUtil.toFirstLowerCase(classname));
//获取字段名
List<Map<String, String>> tableInfo = DBUtil.getTableInfo(connection, tableName);
Set<String> imports = new HashSet<>();
List<String> fields = new ArrayList<>();
List<String> getter_setters = new ArrayList<>();
List<String> intos = new ArrayList<>();
List<String> values = new ArrayList<>();
List<String> sets = new ArrayList<>();
tableInfo.forEach(map -> {
//字段名
String name = map.get("name");
//字段类型--目前得到的是DB类型
String type = map.get("type");
//字段注释
String comment = map.get("comment");
//处理导包
String importStr = ClassesUtil.handlerImport(type);
if (StringUtil.isNotEmptyOrNull(importStr)) {
imports.add(importStr);
}
//处理字段
fields.add(ClassesUtil.handlerField(name, type, comment));
//处理getter/setter
getter_setters.add(ClassesUtil.handlerGetterAndSetter(name, type));
if(!name.equals("id")){
intos.add("\t\t\t<if test=\""+name+"!=null\">\n\t\t\t\t`"+name+"`,\n\t\t\t</if>\n");
values.add("\t\t\t<if test=\""+name+"!=null\">\n\t\t\t\t#{"+name+"},\n\t\t\t</if>\n");
sets.add("\t\t\t<if test=\""+name+"!=null\">\n\t\t\t\t`"+name+"`=#{"+name+"},\n\t\t\t</if>\n");
}
});
String imports_str = "";
for (String str : imports) {
imports_str += str + "\n";
}
rules.put("{{imports}}", imports_str);
String fields_str = "";
for (String str : fields) {
fields_str += str + "\n";
}
rules.put("{{fields}}", fields_str);
String getter_setters_str = "";
for (String str : getter_setters) {
getter_setters_str += str + "\n";
}
rules.put("{{getter_setter}}", getter_setters_str);
//封装insert语句的列
String into = "";
for(String str:intos){
into += str;
}
rules.put("{{into}}",into);
//封装insert语句的值
String valuesStr = "";
for(String str:values){
valuesStr += str;
}
rules.put("{{values}}",valuesStr);
//封装set语句
String setStr = "";
for(String str:sets){
setStr += str;
}
rules.put("{{sets}}",setStr);
return rules;
}
}
三、 核心的抛给程序员使用的类 没什么注释,但是看方法名应该就知道干嘛的了
package com.cms;
import com.cms.template.Template;
import com.cms.util.ClassesUtil;
import com.cms.util.DBUtil;
import com.cms.util.StringUtil;
import com.cms.util.TemplateUtil;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
public class DBHandler {
private Connection connection;
/**
* 一键生成 父子模型、父子DAO、父子XML、service、后台action、web api action
*/
public void auto() {
//获取所有表明
List<String> tables = DBUtil.getTables(connection);
tables.forEach(tableNam -> {
autoOneByTableName(tableNam);
});
}
public void autoOneByTableName(String tableName) {
createModel(tableName);
createBaseModelAndBaseMapper(tableName);
createDAO(tableName);
createBaseDAO(tableName);
createMapper(tableName);
createService(tableName);
createDTO(tableName);
createAction(tableName);
}
public void createBaseModelAndBaseMapper(String tableName) {
if(StringUtil.isEmptyOrNull(baseModelPackage)){
System.err.println("未指定base model包,创建base model失败");
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{baseModelPackage}}"), rules.get("{{classname}}") + "Base.java", Template.CLASS_BASE_TEMPLATE);
if(StringUtil.isEmptyOrNull(baseMapperPackage)){
System.err.println("未指定父级DAO包,创建父级DAO失败");
return;
}
ClassesUtil.write(rules, rules.get("{{baseMapperPackage}}"), rules.get("{{classname}}") + "BaseDAO.xml", Template.BASE_MAPPER_TEMPLATE);
}
public void createBaseDAO(String tableName){
if(StringUtil.isEmptyOrNull(baseDAOPackage)){
System.err.println("未指定base dao包,创建base dao失败");
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{baseDAOPackage}}"), rules.get("{{classname}}") + "BaseDAO.java", Template.BASE_DAO_TEMPLATE);
}
public void createMapper(String tableName) {
if(StringUtil.isEmptyOrNull(mapperPackage)){
System.err.println("未指定DAO包,创建DAO失败");
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{mapperPackage}}"), rules.get("{{classname}}") + "DAO.xml", Template.MAPPER_TEMPLATE);
}
public void createDTO(String tableName) {
if(StringUtil.isEmptyOrNull(pageDTOPackage)){
System.err.println("未指定分页DTO包,创建分页DTO失败");
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{pageDTOPackage}}"), rules.get("{{classname}}") + "PageDTO.java", Template.PAGE_DTO_TEMPLATE);
}
public void createAction(String tableName) {
if(StringUtil.isEmptyOrNull(actionPackage)){
System.err.println("未指定action包,创建action失败");
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{actionPackage}}"), rules.get("{{classname}}") + "Action.java", Template.ACTION_TEMPLATE);
if(StringUtil.isEmptyOrNull(apiActionPackage)){
System.err.println("未指定api action包,创建api action失败");
return;
}
ClassesUtil.write(rules, rules.get("{{apiActionPackage}}"), "API"+rules.get("{{classname}}") + "Action.java", Template.API_ACTION_TEMPLATE);
}
public void createService(String tableName) {
if(StringUtil.isEmptyOrNull(servicePackage)){
System.err.println("未指定service包,创建service失败");
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{servicePackage}}"), rules.get("{{classname}}") + "Service.java", Template.SERVICE_TEMPLATE);
}
public void createDAO(String tableName) {
if(StringUtil.isEmptyOrNull(daoPackage)){
System.err.println("未指定dao包,创建dao失败");
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{daoPackage}}"), rules.get("{{classname}}") + "DAO.java", Template.DAO_TEMPLATE);
}
/**
* 创建子级模型
*/
public void createModel(String tableName) {
if(StringUtil.isEmptyOrNull(modelPackage)){
return;
}
Map<String, String> rules = handlerRules(tableName);
ClassesUtil.write(rules, rules.get("{{modelPackage}}"), rules.get("{{classname}}") + ".java", Template.CLASS_TEMPLATE);
}
private Map<String,String> handlerRules(String tableName){
return TemplateUtil.handlerRules(connection,tableName, separator,
baseModelPackage, modelPackage,
baseDAOPackage, daoPackage,
baseMapperPackage, mapperPackage,
servicePackage, actionPackage,
apiActionPackage, pageDTOPackage,
pageDTO,resultDTO,resultDTOPackage);
}
public DBHandler(String url, String username, String password) {
this.connection = DBUtil.getConn(url, username, password);
}
private String separator;
private String baseModelPackage;
private String modelPackage;
private String baseDAOPackage;
private String daoPackage;
private String baseMapperPackage;
private String mapperPackage;
private String servicePackage;
private String actionPackage;
private String apiActionPackage;
private String pageDTOPackage;
private String pageDTO;
private String resultDTO;
private String resultDTOPackage;
public String getSeparator() {
return separator;
}
public void setSeparator(String separator) {
this.separator = separator;
}
public String getBaseModelPackage() {
return baseModelPackage;
}
public void setBaseModelPackage(String baseModelPackage) {
this.baseModelPackage = baseModelPackage;
}
public String getModelPackage() {
return modelPackage;
}
public void setModelPackage(String modelPackage) {
this.modelPackage = modelPackage;
}
public String getBaseDAOPackage() {
return baseDAOPackage;
}
public void setBaseDAOPackage(String baseDAOPackage) {
this.baseDAOPackage = baseDAOPackage;
}
public String getDaoPackage() {
return daoPackage;
}
public void setDaoPackage(String daoPackage) {
this.daoPackage = daoPackage;
}
public String getBaseMapperPackage() {
return baseMapperPackage;
}
public void setBaseMapperPackage(String baseMapperPackage) {
this.baseMapperPackage = baseMapperPackage;
}
public String getMapperPackage() {
return mapperPackage;
}
public void setMapperPackage(String mapperPackage) {
this.mapperPackage = mapperPackage;
}
public String getServicePackage() {
return servicePackage;
}
public void setServicePackage(String servicePackage) {
this.servicePackage = servicePackage;
}
public String getActionPackage() {
return actionPackage;
}
public void setActionPackage(String actionPackage) {
this.actionPackage = actionPackage;
}
public String getApiActionPackage() {
return apiActionPackage;
}
public void setApiActionPackage(String apiActionPackage) {
this.apiActionPackage = apiActionPackage;
}
public String getPageDTOPackage() {
return pageDTOPackage;
}
public void setPageDTOPackage(String pageDTOPackage) {
this.pageDTOPackage = pageDTOPackage;
}
public String getPageDTO() {
return pageDTO;
}
public void setPageDTO(String pageDTO) {
this.pageDTO = pageDTO;
}
public String getResultDTO() {
return resultDTO;
}
public void setResultDTO(String resultDTO) {
this.resultDTO = resultDTO;
}
public String getResultDTOPackage() {
return resultDTOPackage;
}
public void setResultDTOPackage(String resultDTOPackage) {
this.resultDTOPackage = resultDTOPackage;
}
}
四、 使用
1) 打jar包 maven打jar包 傻瓜式操作 就不上图了
2)将jar包放入maven本地库
3)在项目中添加 就是依赖打的这个jar包 名字和包如果不是我这么定义的 请按照自己的来
<dependency>
<groupId>com.cms</groupId>
<artifactId>cms</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
4)项目中创建个测试类
package com.love.util;
import com.cms.DBHandler;
public class Test {
public static void main(String[] args) {
DBHandler handler = new DBHandler("jdbc:log4jdbc:mysql:///love?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false",
"root","admin");
//数据库表的分隔符 如果你的表是 sys_service 那么就传_ 如果没有 随便传或者空字符串都行
handler.setSeparator("_");
/**
*父级模型的包 为什么要有父级模型?
* 是为了解决项目过程中改表结构
* 我们使用时只是有子模型 可以子模型中定义一些属性来方便我们开发或者给前端返回结果
* 如果后期改表了就不用去动子模型 而父级模型我们一般不使用 只是用来与数据库一一映射的
*/
handler.setBaseModelPackage("com.love.entity.base");
/**
* 子模型的包
*/
handler.setModelPackage("com.love.entity");
/**
* 父级dao所在的包
* 跟父级模型同理 基本的CRUD跟数据库结构挂钩 数据库表改了 那么dao肯定也要改
*/
handler.setBaseDAOPackage("com.love.dao.base");
/**
* 子dao所在的包
*/
handler.setDaoPackage("com.love.dao");
/**
* 父级dao的映射文件xml的包
* 根据习惯不同 有些喜欢把dao和xml合在一起 有些喜欢分开 那这里就分开 实用性稍微强一些
*/
handler.setBaseMapperPackage("com.love.dao.base");
/**
* 子级dao的映射文件xml的包
*/
handler.setMapperPackage("com.love.dao");
/**
* service所在的包
*/
handler.setServicePackage("com.love.service");
/**
* 后台控制器所在的包
*/
handler.setActionPackage("com.love.controller");
/**
* 前端api控制器所在的包
*/
handler.setApiActionPackage("com.love.controller.api");
/**
* dto所在的包
* 这个dto是所有模型的高级查询+分页dto 一般高级查询加分页功能都会在一起 所以一般会创建一个dto来专门做高级查询+分页
* 而且这个dto会继承setPageDTO的参数对应的类
*/
handler.setPageDTOPackage("com.love.dto");
/**
* 结果对象所在的包 这个我单独在下面罗列 单独贴图
*/
handler.setResultDTOPackage("com.love.dto");
/**
* 项目中自己的分页DTO基类 封装了分页和结果的 单独下面贴图
*/
handler.setPageDTO("PageDTO");
/**
* 结果类 单图贴图
*/
handler.setResultDTO("ResultDTO");
/**
* 生成所有表的所有 就是模型->控制器全部
*/
// handler.auto();
/**
* 生成某一张表的全部
*/
handler.autoOneByTableName("table");
//这个方法就是改了表之后需要重新生成模型和doa的和xml的方法
handler.createBaseModelAndBaseMapper("account");
//还有一些单独生成某一个文件的方法
}
}
5) PageDTO 分页dto基类
package com.love.dto;
import java.util.ArrayList;
import java.util.List;
public class PageDTO<T> {
private long page;//当前页
private long pageSize;//每页显示条数
private long total;//总记录数
private long pageCount;//尾页
private List<T> data;//数据集
public PageDTO() {
}
public long getPage() {
return page;
}
public void setPage(long page) {
this.page = page;
}
public long getPageSize() {
return this.pageSize;
}
public void setPageSize(long pageSize) {
this.pageSize = pageSize;
}
public long getTotal() {
return this.total;
}
public void setTotal(long total) {
this.total = total;
if (this.pageSize < 1L || this.pageSize > 100L) {
this.pageSize = 10L;
}
this.pageCount = total / this.pageSize + (long)(total % this.pageSize != 0L ? 1 : 0);
if (this.page > this.pageCount) {
this.page = this.pageCount;
}
if (this.page < 1L) {
this.page = 1L;
}
}
public long getPageCount() {
return this.pageCount;
}
public void setPageCount(long pageCount) {
this.pageCount = pageCount;
}
public List<T> getData() {
if (null == this.data) {
this.data = new ArrayList<T>();
}
return this.data;
}
public void setData(List<T> dataList) {
this.data = dataList;
}
public long getFromRowIndex() {
return (this.page - 1L) * this.pageSize;
}
}
6) ResultDTO结果类
package com.love.dto;
import java.io.Serializable;
public class ResultDTO implements Serializable {
private static final long serialVersionUID = 1L;
private int code;//200或其他 200是正确
private String msg;//操作信息
private Object data;//查询单个获取的信息
private String errMsg;//错误消息,只有错误的时候才有
private ResultDTO() {
}
public static ResultDTO putSuccess(String msg,Object data) {
ResultDTO dto = new ResultDTO();
dto.code = 200;
dto.msg = msg;
dto.data = data;
return dto;
}
public static ResultDTO putSuccess(String msg) {
ResultDTO dto = new ResultDTO();
dto.code = 200;
dto.msg = msg;
dto.data = null;
return dto;
}
public static ResultDTO put400(String msg) {
return putError(msg, msg,400);
}
public static ResultDTO put400(String msg,String errMsg) {
return putError(msg, errMsg,400);
}
public static ResultDTO put401(String msg,String errMsg) {
return putError(msg, errMsg,401);
}
public static ResultDTO put500(String msg,String errMsg) {
return putError(msg, errMsg,500);
}
public static ResultDTO putError(String errMsg) {
ResultDTO dto = new ResultDTO();
dto.code = 500;
dto.msg = null;
dto.data = null;
dto.errMsg = errMsg;
return dto;
}
public static ResultDTO putError(String msg,String errMsg,int code) {
ResultDTO dto = new ResultDTO();
dto.code = code;
dto.msg = msg;
dto.data = null;
dto.errMsg = errMsg;
return dto;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
}
五、 结果
1) 父级模型
2)子级模型 自定义属性写在这个模型中,下述方法不会覆盖这个文件
3) 父级dao
4)子级dao
5)父级xml dao的sql不要写在这个xml
6)子级xml 自定义的sql写在这里
7)service logicWhereSql和logicSetSql都是逻辑查询和逻辑删除相关的,如果表有逻辑字段 deleted -1代表删除 那么:
logicWhereSql = "deleted != -1"
logicSetSql = "set deleted = -1"
8)控制器 api的控制器跟这个一样
9)dto 分页类