父依赖
<!--Maven管理版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<mybatisplus.version>3.3.1</mybatisplus.version>
<druid.version>1.1.13</druid.version>
<commons.lang.version>2.6</commons.lang.version>
<commons.io.version>2.5</commons.io.version>
<commons.configuration.version>1.10</commons.configuration.version>
<fastjson.version>1.2.60</fastjson.version>
<velocity.version>1.7</velocity.version>
<pagehelper.spring.boot.version>1.2.5</pagehelper.spring.boot.version>
<mysql.version>8.0.17</mysql.version>
<mssql.version>4.0</mssql.version>
<oracle.version>11.2.0.3</oracle.version>
<mongo.version>3.11.0</mongo.version>
</properties>
Maven管理依赖
<!--集成人人开源代码生成器需要的依赖-->
<!-- mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--常用工具类-->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<!--IO工具类包-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<!--操作配置文件的工具包-->
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>${commons.configuration.version}</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--页面模板引擎-->
<dependency>
<artifactId>velocity</artifactId>
<groupId>org.apache.velocity</groupId>
<version>${velocity.version}</version>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.spring.boot.version}</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- oracle驱动 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>${oracle.version}</version>
</dependency>
<!-- sqlserver驱动 -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>${mssql.version}</version>
</dependency>
<!-- postgresql驱动 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- mongo驱动 -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo.version}</version>
</dependency>
<!--mysql连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.9</version>
</dependency>
<!--jdbc连接池-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--生产配置元数据-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--引入lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
entity(实体类)
ColumnEntity
/**
* 列的属性
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年12月20日 上午12:01:45
*/
public class ColumnEntity {
//列名
private String columnName;
//列名类型
private String dataType;
//列名备注
private String comments;
//属性名称(第一个字母大写),如:user_name => UserName
private String attrName;
//属性名称(第一个字母小写),如:user_name => userName
private String attrname;
//属性类型
private String attrType;
//auto_increment
private String extra;
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getAttrname() {
return attrname;
}
public void setAttrname(String attrname) {
this.attrname = attrname;
}
public String getAttrName() {
return attrName;
}
public void setAttrName(String attrName) {
this.attrName = attrName;
}
public String getAttrType() {
return attrType;
}
public void setAttrType(String attrType) {
this.attrType = attrType;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}
TableEntity
import java.util.List;
/**
* 表数据
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年12月20日 上午12:02:55
*/
public class TableEntity {
//表的名称
private String tableName;
//表的备注
private String comments;
//表的主键
private ColumnEntity pk;
//表的列名(不包含主键)
private List<ColumnEntity> columns;
//类名(第一个字母大写),如:sys_user => SysUser
private String className;
//类名(第一个字母小写),如:sys_user => sysUser
private String classname;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public ColumnEntity getPk() {
return pk;
}
public void setPk(ColumnEntity pk) {
this.pk = pk;
}
public List<ColumnEntity> getColumns() {
return columns;
}
public void setColumns(List<ColumnEntity> columns) {
this.columns = columns;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
}
MongoDefinition
import com.yongyuankuaile.product.generotor.adaptor.MongoTableInfoAdaptor;
import org.apache.commons.collections.CollectionUtils;
import java.io.Serializable;
import java.util.*;
/**
* 解析表之后得到的信息实体
* 换句话说这个类就是一张mongo一张表的内容
*
* @author gxz 514190950@qq.com
*/
public class MongoDefinition implements Serializable {
/***属性名**/
private String propertyName;
/***属性类型 对应mongodb api $type 如果没有类型 表示这是一个顶层实体 而不是内嵌属性**/
private Integer type;
/***此属性是否是数组**/
private boolean array = false;
/***如果此属性是对象 那么他仍然有此类型的子类**/
private List<MongoDefinition> child;
public List<MongoGeneratorEntity> getChildrenInfo(String tableName) {
List<MongoGeneratorEntity> result = new ArrayList<>();
MongoGeneratorEntity info = new MongoGeneratorEntity();
// 表信息
Map<String, String> tableInfo = MongoTableInfoAdaptor.tableInfo(tableName);
// 列名信息
List<Map<String, String>> columnsInfo = new ArrayList<>();
info.setColumns(columnsInfo);
info.setTableInfo(tableInfo);
result.add(info);
List<MongoDefinition> child = this.getChild();
for (MongoDefinition mongoDefinition : child) {
Map<String, String> columnInfo = new HashMap<>(5);
columnInfo.put("columnName", mongoDefinition.getPropertyName());
columnInfo.put("dataType", Type.typeInfo(mongoDefinition.getType()));
columnInfo.put("extra", mongoDefinition.isArray() ? "array" : "");
columnsInfo.add(columnInfo);
if (mongoDefinition.hasChild()) {
result.addAll(mongoDefinition.getChildrenInfo(mongoDefinition.getPropertyName()));
}
}
return result;
}
public boolean hasChild() {
final int objectType = 3;
return type == null || Objects.equals(type, objectType) || CollectionUtils.isNotEmpty(child);
}
public boolean primaryBean() {
return type == null;
}
public MongoDefinition setType(Integer type) {
this.type = type;
return this;
}
public String getPropertyName() {
return propertyName;
}
public MongoDefinition setPropertyName(String propertyName) {
this.propertyName = propertyName;
return this;
}
public Integer getType() {
return type;
}
public boolean isArray() {
return array;
}
public MongoDefinition setArray(boolean array) {
this.array = array;
return this;
}
public List<MongoDefinition> getChild() {
return child;
}
public MongoDefinition setChild(List<MongoDefinition> child) {
this.child = child;
return this;
}
}
MongoGeneratorEntity
import com.yongyuankuaile.product.generotor.entity.TableEntity;
import java.util.List;
import java.util.Map;
/**
* mysql一张表只需要一个表信息和列名信息
* 但是mongo一张表可能需要多个实体类 所以单独用一个bean封装
*
* @author gxz
* @date 2020/5/10 0:14
*/
public class MongoGeneratorEntity {
/***表信息**/
private Map<String, String> tableInfo;
/***主类的列名信息**/
private List<Map<String, String>> columns;
public TableEntity toTableEntity() {
TableEntity tableEntity = new TableEntity();
Map<String, String> tableInfo = this.tableInfo;
tableEntity.setTableName(tableInfo.get("tableName"));
tableEntity.setComments("");
return tableEntity;
}
public Map<String, String> getTableInfo() {
return tableInfo;
}
public MongoGeneratorEntity setTableInfo(Map<String, String> tableInfo) {
this.tableInfo = tableInfo;
return this;
}
public List<Map<String, String>> getColumns() {
return columns;
}
public MongoGeneratorEntity setColumns(List<Map<String, String>> columns) {
this.columns = columns;
return this;
}
}
Type
import java.util.Objects;
public enum Type {
/***
* 类型 和对应mongodb api 的$type的数字
**/
varchar(2),
NUMBER(16),
bigint(18),
OBJECT(3),
ARRAY(4),
date(9),
bit(8),
DOUBLE(1);
private final int num;
Type(int num) {
this.num = num;
}
public static String typeInfo(int num) {
Type[] values = values();
for (Type value : values) {
if (Objects.equals(num, value.num)) {
return value.toString();
}
}
return null;
}
}
utils (工具类)
Constant
/**
* 常量
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年11月15日 下午1:23:52
*/
public class Constant {
}
DateUtils
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期处理
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年12月21日 下午12:53:33
*/
public class DateUtils {
/** 时间格式(yyyy-MM-dd) */
public final static String DATE_PATTERN = "yyyy-MM-dd";
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
public static String format(Date date) {
return format(date, DATE_PATTERN);
}
public static String format(Date date, String pattern) {
if(date != null){
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
}
GenUtils
import com.yongyuankuaile.product.generotor.config.MongoManager;
import com.yongyuankuaile.product.generotor.entity.ColumnEntity;
import com.yongyuankuaile.product.generotor.entity.TableEntity;
import com.yongyuankuaile.product.generotor.entity.mongo.MongoDefinition;
import com.yongyuankuaile.product.generotor.entity.mongo.MongoGeneratorEntity;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 代码生成器 工具类
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年12月19日 下午11:40:24
*/
public class GenUtils {
private static String currentTableName;
public static List<String> getTemplates() {
List<String> templates = new ArrayList<String>();
templates.add("template/Entity.java.vm");
templates.add("template/Dao.xml.vm");
templates.add("template/menu.sql.vm");
templates.add("template/Service.java.vm");
templates.add("template/ServiceImpl.java.vm");
templates.add("template/Controller.java.vm");
templates.add("template/Dao.java.vm");
templates.add("template/index.vue.vm");
templates.add("template/add-or-update.vue.vm");
if (MongoManager.isMongo()) {
// mongo不需要mapper、sql 实体类需要替换
templates.remove(0);
templates.remove(1);
templates.remove(2);
templates.add("template/MongoEntity.java.vm");
}
return templates;
}
public static List<String> getMongoChildTemplates() {
List<String> templates = new ArrayList<String>();
templates.add("template/MongoChildrenEntity.java.vm");
return templates;
}
/**
* 生成代码
*/
public static void generatorCode(Map<String, String> table,
List<Map<String, String>> columns, ZipOutputStream zip) {
//配置信息
Configuration config = getConfig();
boolean hasBigDecimal = false;
boolean hasList = false;
//表信息
TableEntity tableEntity = new TableEntity();
tableEntity.setTableName(table.get("tableName"));
tableEntity.setComments(table.get("tableComment"));
//表名转换成Java类名
String className = tableToJava(tableEntity.getTableName(), config.getStringArray("tablePrefix"));
tableEntity.setClassName(className);
tableEntity.setClassname(StringUtils.uncapitalize(className));
//列信息
List<ColumnEntity> columsList = new ArrayList<>();
for (Map<String, String> column : columns) {
ColumnEntity columnEntity = new ColumnEntity();
columnEntity.setColumnName(column.get("columnName"));
columnEntity.setDataType(column.get("dataType"));
columnEntity.setComments(column.get("columnComment"));
columnEntity.setExtra(column.get("extra"));
//列名转换成Java属性名
String attrName = columnToJava(columnEntity.getColumnName());
columnEntity.setAttrName(attrName);
columnEntity.setAttrname(StringUtils.uncapitalize(attrName));
//列的数据类型,转换成Java类型
String attrType = config.getString(columnEntity.getDataType(), columnToJava(columnEntity.getDataType()));
columnEntity.setAttrType(attrType);
if (!hasBigDecimal && attrType.equals("BigDecimal")) {
hasBigDecimal = true;
}
if (!hasList && "array".equals(columnEntity.getExtra())) {
hasList = true;
}
//是否主键
if ("PRI".equalsIgnoreCase(column.get("columnKey")) && tableEntity.getPk() == null) {
tableEntity.setPk(columnEntity);
}
columsList.add(columnEntity);
}
tableEntity.setColumns(columsList);
//没主键,则第一个字段为主键
if (tableEntity.getPk() == null) {
tableEntity.setPk(tableEntity.getColumns().get(0));
}
//设置velocity资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
String mainPath = config.getString("mainPath");
mainPath = StringUtils.isBlank(mainPath) ? "com.yongyuankuaile.product.generotor" : mainPath;
//封装模板数据
Map<String, Object> map = new HashMap<>();
map.put("tableName", tableEntity.getTableName());
map.put("comments", tableEntity.getComments());
map.put("pk", tableEntity.getPk());
map.put("className", tableEntity.getClassName());
map.put("classname", tableEntity.getClassname());
map.put("pathName", tableEntity.getClassname().toLowerCase());
map.put("columns", tableEntity.getColumns());
map.put("hasBigDecimal", hasBigDecimal);
map.put("hasList", hasList);
map.put("mainPath", mainPath);
map.put("package", config.getString("package"));
map.put("moduleName", config.getString("moduleName"));
map.put("author", config.getString("author"));
map.put("email", config.getString("email"));
map.put("datetime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
VelocityContext context = new VelocityContext(map);
//获取模板列表
List<String> templates = getTemplates();
for (String template : templates) {
//渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, sw);
try {
//添加到zip
zip.putNextEntry(new ZipEntry(getFileName(template, tableEntity.getClassName(), config.getString("package"), config.getString("moduleName"))));
IOUtils.write(sw.toString(), zip, "UTF-8");
IOUtils.closeQuietly(sw);
zip.closeEntry();
} catch (IOException e) {
throw new RRException("渲染模板失败,表名:" + tableEntity.getTableName(), e);
}
}
}
/**
* 生成mongo其他实体类的代码
*/
public static void generatorMongoCode(String[] tableNames, ZipOutputStream zip) {
for (String tableName : tableNames) {
MongoDefinition info = MongoManager.getInfo(tableName);
currentTableName = tableName;
List<MongoGeneratorEntity> childrenInfo = info.getChildrenInfo(tableName);
childrenInfo.remove(0);
for (MongoGeneratorEntity mongoGeneratorEntity : childrenInfo) {
generatorChildrenBeanCode(mongoGeneratorEntity, zip);
}
}
}
private static void generatorChildrenBeanCode(MongoGeneratorEntity mongoGeneratorEntity, ZipOutputStream zip) {
//配置信息
Configuration config = getConfig();
boolean hasList = false;
//表信息
TableEntity tableEntity = mongoGeneratorEntity.toTableEntity();
//表名转换成Java类名
String className = tableToJava(tableEntity.getTableName(), config.getStringArray("tablePrefix"));
tableEntity.setClassName(className);
tableEntity.setClassname(StringUtils.uncapitalize(className));
//列信息
List<ColumnEntity> columsList = new ArrayList<>();
for (Map<String, String> column : mongoGeneratorEntity.getColumns()) {
ColumnEntity columnEntity = new ColumnEntity();
String columnName = column.get("columnName");
if (columnName.contains(".")) {
columnName = columnName.substring(columnName.lastIndexOf(".") + 1);
}
columnEntity.setColumnName(columnName);
columnEntity.setDataType(column.get("dataType"));
columnEntity.setExtra(column.get("extra"));
//列名转换成Java属性名
String attrName = columnToJava(columnEntity.getColumnName());
columnEntity.setAttrName(attrName);
columnEntity.setAttrname(StringUtils.uncapitalize(attrName));
//列的数据类型,转换成Java类型
String attrType = config.getString(columnEntity.getDataType(), columnToJava(columnEntity.getDataType()));
columnEntity.setAttrType(attrType);
if (!hasList && "array".equals(columnEntity.getExtra())) {
hasList = true;
}
columsList.add(columnEntity);
}
tableEntity.setColumns(columsList);
//设置velocity资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
String mainPath = config.getString("mainPath");
mainPath = StringUtils.isBlank(mainPath) ? "com.yongyuankuaile.product.generotor" : mainPath;
//封装模板数据
Map<String, Object> map = new HashMap<>();
map.put("tableName", tableEntity.getTableName());
map.put("comments", tableEntity.getComments());
map.put("pk", tableEntity.getPk());
map.put("className", tableEntity.getClassName());
map.put("classname", tableEntity.getClassname());
map.put("pathName", tableEntity.getClassname().toLowerCase());
map.put("columns", tableEntity.getColumns());
map.put("hasList", hasList);
map.put("mainPath", mainPath);
map.put("package", config.getString("package"));
map.put("moduleName", config.getString("moduleName"));
map.put("author", config.getString("author"));
map.put("email", config.getString("email"));
map.put("datetime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
VelocityContext context = new VelocityContext(map);
//获取模板列表
List<String> templates = getMongoChildTemplates();
for (String template : templates) {
//渲染模板
StringWriter sw = new StringWriter();
Template tpl = Velocity.getTemplate(template, "UTF-8");
tpl.merge(context, sw);
try {
//添加到zip
zip.putNextEntry(new ZipEntry(getFileName(template, tableEntity.getClassName(), config.getString("package"), config.getString("moduleName"))));
IOUtils.write(sw.toString(), zip, "UTF-8");
IOUtils.closeQuietly(sw);
zip.closeEntry();
} catch (IOException e) {
throw new RRException("渲染模板失败,表名:" + tableEntity.getTableName(), e);
}
}
}
/**
* 列名转换成Java属性名
*/
public static String columnToJava(String columnName) {
return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "");
}
/**
* 表名转换成Java类名
*/
public static String tableToJava(String tableName, String[] tablePrefixArray) {
if (null != tablePrefixArray && tablePrefixArray.length > 0) {
for (String tablePrefix : tablePrefixArray) {
if (tableName.startsWith(tablePrefix)){
tableName = tableName.replaceFirst(tablePrefix, "");
}
}
}
return columnToJava(tableName);
}
/**
* 获取配置信息
*/
public static Configuration getConfig() {
try {
return new PropertiesConfiguration("generator.properties");
} catch (ConfigurationException e) {
throw new RRException("获取配置文件失败,", e);
}
}
/**
* 获取文件名
*/
public static String getFileName(String template, String className, String packageName, String moduleName) {
String packagePath = "main" + File.separator + "java" + File.separator;
if (StringUtils.isNotBlank(packageName)) {
packagePath += packageName.replace(".", File.separator) + File.separator + moduleName + File.separator;
}
if (template.contains("MongoChildrenEntity.java.vm")) {
return packagePath + "entity" + File.separator + "inner" + File.separator + currentTableName+ File.separator + splitInnerName(className)+ "InnerEntity.java";
}
if (template.contains("Entity.java.vm") || template.contains("MongoEntity.java.vm")) {
return packagePath + "entity" + File.separator + className + "Entity.java";
}
if (template.contains("Dao.java.vm")) {
return packagePath + "dao" + File.separator + className + "Dao.java";
}
if (template.contains("Service.java.vm")) {
return packagePath + "service" + File.separator + className + "Service.java";
}
if (template.contains("ServiceImpl.java.vm")) {
return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
}
if (template.contains("Controller.java.vm")) {
return packagePath + "controller" + File.separator + className + "Controller.java";
}
if (template.contains("Dao.xml.vm")) {
return "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + moduleName + File.separator + className + "Dao.xml";
}
if (template.contains("menu.sql.vm")) {
return className.toLowerCase() + "_menu.sql";
}
if (template.contains("index.vue.vm")) {
return "main" + File.separator + "resources" + File.separator + "src" + File.separator + "views" + File.separator + "modules" +
File.separator + moduleName + File.separator + className.toLowerCase() + ".vue";
}
if (template.contains("add-or-update.vue.vm")) {
return "main" + File.separator + "resources" + File.separator + "src" + File.separator + "views" + File.separator + "modules" +
File.separator + moduleName + File.separator + className.toLowerCase() + "-add-or-update.vue";
}
return null;
}
private static String splitInnerName(String name){
name = name.replaceAll("\\.","_");
return name;
}
}
HttpStatus
/**
* 返回状态码
*
* @author ruoyi
*/
public class HttpStatus
{
/**
* 操作成功
*/
public static final int SUCCESS = 200;
/**
* 对象创建成功
*/
public static final int CREATED = 201;
/**
* 请求已经被接受
*/
public static final int ACCEPTED = 202;
/**
* 操作已经执行成功,但是没有返回数据
*/
public static final int NO_CONTENT = 204;
/**
* 资源已被移除
*/
public static final int MOVED_PERM = 301;
/**
* 重定向
*/
public static final int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
public static final int NOT_MODIFIED = 304;
/**
* 参数列表错误(缺少,格式不匹配)
*/
public static final int BAD_REQUEST = 400;
/**
* 未授权
*/
public static final int UNAUTHORIZED = 401;
/**
* 访问受限,授权过期
*/
public static final int FORBIDDEN = 403;
/**
* 资源,服务未找到
*/
public static final int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
public static final int BAD_METHOD = 405;
/**
* 资源冲突,或者资源被锁
*/
public static final int CONFLICT = 409;
/**
* 不支持的数据,媒体类型
*/
public static final int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
public static final int ERROR = 500;
/**
* 接口未实现
*/
public static final int NOT_IMPLEMENTED = 501;
}
MongoScanner
import com.mongodb.BasicDBObject;
import com.mongodb.MongoCommandException;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.yongyuankuaile.product.generotor.config.MongoManager;
import com.yongyuankuaile.product.generotor.entity.mongo.MongoDefinition;
import com.yongyuankuaile.product.generotor.entity.mongo.Type;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;
/**
* @author: gxz 514190950@qq.com
**/
public class MongoScanner {
private Logger logger = LoggerFactory.getLogger(getClass());
private MongoCollection<Document> collection;
final private int scanCount;
private List<String> colNames;
private MongoDefinition mongoDefinition;
private final static int[] TYPE = {3, 16, 18, 8, 9, 2, 1};
private final static int ARRAY_TYPE = 4;
private final static int MAX_COUNT = 200000;
private final static int DEFAULT_COUNT = 100000;
public MongoScanner(MongoCollection<Document> collection) {
this.collection = collection;
this.scanCount = DEFAULT_COUNT;
scan();
}
private void scan() {
// 初始化
initColNames();
// 解析属性值
mongoDefinition = scanType();
MongoManager.putInfo(collection.getNamespace().getCollectionName(), mongoDefinition);
// 解析完成之后释放链接资源
this.collection = null;
}
public MongoDefinition getProduct() {
return mongoDefinition;
}
/**
* 功能描述:分组发送聚合函数(获得一级属性名)
*
* @author : gxz
*/
public List<String> groupAggregation(Integer skip, Integer limit) throws MongoCommandException {
skip = skip == null ? 0 : skip;
limit = limit == null ? scanCount : limit;
MongoCollection<Document> collection = this.collection;
BasicDBObject $project = new BasicDBObject("$project", new BasicDBObject("arrayofkeyvalue", new BasicDBObject("$objectToArray", "$$ROOT")));
BasicDBObject $unwind = new BasicDBObject("$unwind", "$arrayofkeyvalue");
BasicDBObject $skip = new BasicDBObject("$skip", skip);
BasicDBObject $limit = new BasicDBObject("$limit", limit);
BasicDBObject filed = new BasicDBObject("_id", "null");
filed.append("allkeys", new BasicDBObject("$addToSet", "$arrayofkeyvalue.k"));
BasicDBObject $group = new BasicDBObject("$group", filed);
List<BasicDBObject> dbStages = Arrays.asList($project, $skip, $limit, $unwind, $group);
// System.out.println(dbStages); 发送的聚合函数 获得所有参数名称
AggregateIterable<Document> aggregate = collection.aggregate(dbStages);
Document document = aggregate.first();
if (document == null) {
BasicDBObject existsQuery = new BasicDBObject("$ROOT", new BasicDBObject("$exists", true));
MongoCursor<Document> existsList = collection.find(existsQuery).limit(100).iterator();
Set<String> keySet = new HashSet<>();
while (existsList.hasNext()) {
Document next = existsList.next();
Map<String, Object> keyMap = (Document) next.get("$ROOT");
keySet.addAll(keyMap.keySet());
}
return new ArrayList<>(keySet);
} else {
return (List<String>) document.get("allkeys");
}
}
/**
* 如果一个文档是对象类型 获得这个属性的下一级的属性名的集合
* 例子: user:{name:"张三",age:12} 传入user 返回[name,age]
*
* @param parameterName 上层参数名 这个参数名可以包含一个或多个.
* 注: 参数传递之前需确认: 1.上层属性一定是对象类型
* @return 返回这个属性内的所有属性名
*/
public Set<String> getNextParameterNames(String parameterName) {
Document condition = new Document(parameterName, new Document("$exists", true));
Document match = new Document("$match", condition);
String unwindName = parameterName;
if (parameterName.contains(".")) {
unwindName = parameterName.split("\\.")[0];
}
Document unwind = new Document("$unwind", "$" + unwindName);
Document limit = new Document("$limit", 3000);
Document project = new Document("$project", new Document("list", "$" + parameterName).append("_id", false));
Document unwind2 = new Document("$unwind", "$list");
AggregateIterable<Document> aggregate = this.collection.aggregate(Arrays.asList(match, unwind, limit, project, unwind2));
Set<String> names = new HashSet<>();
for (Document document : aggregate) {
Object list = document.get("list");
if (list instanceof Map) {
Set<String> documentNames = ((Document) list).keySet();
names.addAll(documentNames);
}
}
logger.info("解析" + parameterName + "有" + names.size() + "个子属性");
return names;
}
/**
* 功能描述:提供属性名 解析属性类型
* 获取相应的属性信息 封装成generator对象
*
* @return : 解析之后的Model {@see #MongoDefinition}
* @param: propertyName 属性名 可以是层级名 比如 name 也可以是info.name
* @see MongoDefinition
*/
public MongoDefinition processNameType(String propertyName) {
MongoCollection<Document> collection = this.collection;
MongoDefinition result = new MongoDefinition();
if ("_id".equals(propertyName)) {
result.setType(2);
result.setPropertyName("_id");
return result;
}
result.setPropertyName(propertyName);
MongoCursor<Document> isArray = collection.find(new Document(propertyName, new Document("$type", ARRAY_TYPE))).limit(1).iterator();
if (isArray.hasNext()) {
result.setArray(true);
for (int i : TYPE) {
MongoCursor<Document> iterator = collection.find(new Document(propertyName, new Document("$type", i))).limit(1).iterator();
if (iterator.hasNext()) {
if (i == 3) {
result.setChild(this.produceChildList(propertyName));
}
//1是double 2是string 3是对象 4是数组 16是int 18 是long
result.setType(i);
logger.info("解析[" + propertyName + "]是[List][" + Type.typeInfo(result.getType()) + "]");
return result;
}
}
} else {
for (int i : TYPE) {
MongoCursor<Document> iterator = collection.find(new Document(propertyName, new Document("$type", i))).limit(1).iterator();
if (iterator.hasNext()) {
if (i == 3) {
result.setChild(this.produceChildList(propertyName));
}
//1是double 2是string 3是对象 4是数组 16是int 18 是long
//到这里就是数组了
result.setType(i);
logger.info("解析[" + propertyName + "]是[" + Type.typeInfo(result.getType()) + "]");
return result;
}
}
result.setType(2);
}
logger.info("解析[" + propertyName + "]是[" + Type.typeInfo(result.getType()) + "]");
return result;
}
private List<MongoDefinition> produceChildList(String parentName) {
Set<String> nextParameterNames = this.getNextParameterNames(parentName);
List<String> strings = new ArrayList<>(nextParameterNames);
List<String> collect = strings.stream().map(name -> parentName + "." + name).collect(Collectors.toList());
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<List<MongoDefinition>> task = new ForkJoinProcessType(collect);
return pool.invoke(task);
}
private List<String> distinctAndJoin(List<String> a, List<String> b) {
a.removeAll(b);
a.addAll(b);
return a;
}
/**
* 功能描述:解析这个集合的列名 用ForkJoin框架实现
*/
private void initColNames() {
long start = System.currentTimeMillis();
int scan = this.scanCount;
long count = this.collection.countDocuments();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<List<String>> task;
if (count > (long) scan) {
task = new ForkJoinGetProcessName(0, scan);
} else {
task = new ForkJoinGetProcessName(0, (int) count);
}
this.colNames = pool.invoke(task);
logger.info("collection[" + this.collection.getNamespace().getCollectionName() +
"]初始化列名成功..... 用时: " + (System.currentTimeMillis() - start) + "毫秒");
}
private MongoDefinition scanType() {
MongoDefinition result = new MongoDefinition();
List<String> colNames = this.colNames;
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<List<MongoDefinition>> task = new ForkJoinProcessType(colNames);
List<MongoDefinition> invoke = pool.invoke(task);
return result.setChild(invoke).setPropertyName(this.collection.getNamespace().getCollectionName());
}
/**
* 功能描述:forkJoin多线程框架的实现 通过业务拆分解析类型
*/
class ForkJoinProcessType extends RecursiveTask<List<MongoDefinition>> {
List<String> names;
private final int THRESHOLD = 6;
ForkJoinProcessType(List<String> names) {
this.names = names;
}
@Override
protected List<MongoDefinition> compute() {
if (names.size() <= THRESHOLD) {
List<MongoDefinition> result = new ArrayList<>();
for (String name : names) {
MongoDefinition childrenDefinition = processNameType(name);
result.add(childrenDefinition);
}
return result;
} else {
int size = names.size();
int middle = size / 2;
List<String> leftList = names.subList(0, middle);
List<String> rightList = names.subList(middle, size);
ForkJoinProcessType pre = new ForkJoinProcessType(leftList);
pre.fork();
ForkJoinProcessType next = new ForkJoinProcessType(rightList);
next.fork();
return mergeList(pre.join(), next.join());
}
}
}
/**
* 功能描述:forkJoin多线程框架的实现 通过业务拆分获得属性名
*/
class ForkJoinGetProcessName extends RecursiveTask<List<String>> {
private int begin; //查询开始位置
private int end;
private final int THRESHOLD = 5000;
ForkJoinGetProcessName(int begin, int end) {
this.begin = begin;
this.end = end;
}
@Override
protected List<String> compute() {
int count = end - begin;
if (THRESHOLD >= count) {
return groupAggregation(begin, count);
} else {
int middle = (begin + end) / 2;
ForkJoinGetProcessName pre = new ForkJoinGetProcessName(begin, middle);
pre.fork();
ForkJoinGetProcessName next = new ForkJoinGetProcessName(middle + 1, end);
next.fork();
return distinctAndJoin(pre.join(), next.join()); //去重合并
}
}
}
public <T> List<T> mergeList(List<T> list1, List<T> list2){
list1.addAll(list2);
return list1;
}
}
PageUtils
import java.io.Serializable;
import java.util.List;
/**
* 分页工具类
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年11月4日 下午12:59:00
*/
public class PageUtils implements Serializable {
private static final long serialVersionUID = 1L;
//总记录数
private int totalCount;
//每页记录数
private int pageSize;
//总页数
private int totalPage;
//当前页数
private int currPage;
//列表数据
private List<?> list;
/**
* 分页
* @param list 列表数据
* @param totalCount 总记录数
* @param pageSize 每页记录数
* @param currPage 当前页数
*/
public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
this.list = list;
this.totalCount = totalCount;
this.pageSize = pageSize;
this.currPage = currPage;
this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrPage() {
return currPage;
}
public void setCurrPage(int currPage) {
this.currPage = currPage;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}
}
Query
package com.yongyuankuaile.product.generotor.utils;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
@ApiModel(
description = "查询条件"
)
@Data
@Accessors(chain = true)
public class Query extends LinkedHashMap<String, Object> {
//当前页面
@TableField(exist = false)
private Integer current;
//每页条数
@TableField(exist = false)
private Integer size;
public Query(Map<String, Object> params){
this.putAll(params);
//分页参数
this.current = Integer.parseInt(params.get("current").toString());
this.size = Integer.parseInt(params.get("size").toString());
this.put("offset", (current - 1) * size);
this.put("current", current);
this.put("size", size);
}
/**
* 分页、计算page
* @return
*/
public void getHandlePage(){
current = (current-1)*size;
}
}
R
import java.io.Serializable;
/**
* 响应信息主体
*统一返回数据格式
* @author ruoyi
*/
public class R<T> implements Serializable
{
private static final long serialVersionUID = 1L;
/** 成功 */
public static final int SUCCESS = HttpStatus.SUCCESS;
/** 失败 */
public static final int FAIL = HttpStatus.ERROR;
/*
* 状态码
* */
private Integer code;
/*
* 状态码含义
* */
private String msg;
/*
* 状态码含义描述
* */
private T data;
public static <T> R<T> ok()
{
return restResult(null, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data)
{
return restResult(data, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data, String msg)
{
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail()
{
return restResult(null, FAIL, "操作失败");
}
public static <T> R<T> fail(String msg)
{
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data)
{
return restResult(data, FAIL, "操作失败");
}
public static <T> R<T> fail(T data, String msg)
{
return restResult(data, FAIL, msg);
}
public static <T> R<T> fail(int code, String msg)
{
return restResult(null, code, msg);
}
private static <T> R<T> restResult(T data, int code, String msg)
{
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
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 T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
public R() {
}
public R(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public R(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
}
RRException
/**
* 自定义异常
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年10月27日 下午10:11:27
*/
public class RRException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public RRException(String msg) {
super(msg);
this.msg = msg;
}
public RRException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public RRException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public RRException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
RRExceptionHandler
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 异常处理器
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年10月27日 下午10:16:19
*/
@Component
public class RRExceptionHandler implements HandlerExceptionResolver {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
R r = new R();
try {
response.setContentType("application/json;charset=utf-8");
response.setCharacterEncoding("utf-8");
if (ex instanceof RRException) {
r.ok("code", String.valueOf(((RRException) ex).getCode()));
r.ok("msg", ex.getMessage());
}else if(ex instanceof DuplicateKeyException){
r = R.fail("数据库中已存在该记录");
}else{
r = R.fail();
}
//记录异常日志
logger.error(ex.getMessage(), ex);
String json = JSON.toJSONString(r);
response.getWriter().print(json);
} catch (Exception e) {
logger.error("RRExceptionHandler 异常处理失败", e);
}
return new ModelAndView();
}
}
Controller层
import com.yongyuankuaile.product.generotor.service.SysGeneratorService;
import com.yongyuankuaile.product.generotor.utils.PageUtils;
import com.yongyuankuaile.product.generotor.utils.Query;
import com.yongyuankuaile.product.generotor.utils.R;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
/**
* 代码生成器
*
* @author Mark sunlightcs@gmail.com
*/
@Controller
@RequestMapping("/sys/generator")
public class SysGeneratorController {
@Autowired
private SysGeneratorService sysGeneratorService;
/**
* 列表
*/
@ResponseBody
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
PageUtils pageUtil = sysGeneratorService.queryList(new Query(params));
return R.ok(pageUtil);
}
/**
* 生成代码
*/
@RequestMapping("/code")
public void code(String tables, HttpServletResponse response) throws IOException{
byte[] data = sysGeneratorService.generatorCode(tables.split(","));
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=\"renren.zip\"");
response.addHeader("Content-Length", "" + data.length);
response.setContentType("application/octet-stream; charset=UTF-8");
IOUtils.write(data, response.getOutputStream());
}
}
Service层
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.yongyuankuaile.product.generotor.config.MongoManager;
import com.yongyuankuaile.product.generotor.dao.GeneratorDao;
import com.yongyuankuaile.product.generotor.dao.MongoDBGeneratorDao;
import com.yongyuankuaile.product.generotor.factory.MongoDBCollectionFactory;
import com.yongyuankuaile.product.generotor.utils.GenUtils;
import com.yongyuankuaile.product.generotor.utils.PageUtils;
import com.yongyuankuaile.product.generotor.utils.Query;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipOutputStream;
/**
* 代码生成器
*
* @author Mark sunlightcs@gmail.com
*/
@Service
public class SysGeneratorService {
@Autowired
private GeneratorDao generatorDao;
public PageUtils queryList(Query query) {
Page<?> page = PageHelper.startPage(query.getCurrent(), query.getSize());
List<Map<String, Object>> list = generatorDao.queryList(query);
int total = (int) page.getTotal();
if (generatorDao instanceof MongoDBGeneratorDao) {
total = MongoDBCollectionFactory.getCollectionTotal(query);
}
return new PageUtils(list, total, query.getSize(), query.getCurrent());
}
public Map<String, String> queryTable(String tableName) {
return generatorDao.queryTable(tableName);
}
public List<Map<String, String>> queryColumns(String tableName) {
return generatorDao.queryColumns(tableName);
}
public byte[] generatorCode(String[] tableNames) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
for (String tableName : tableNames) {
//查询表信息
Map<String, String> table = queryTable(tableName);
//查询列信息
List<Map<String, String>> columns = queryColumns(tableName);
//生成代码
GenUtils.generatorCode(table, columns, zip);
}
if (MongoManager.isMongo()) {
GenUtils.generatorMongoCode(tableNames, zip);
}
IOUtils.closeQuietly(zip);
return outputStream.toByteArray();
}
}
Dao层
GeneratorDao
import java.util.List;
import java.util.Map;
/**
* 数据库接口
*
* @author Mark sunlightcs@gmail.com
* @since 2018-07-24
*/
public interface GeneratorDao {
List<Map<String, Object>> queryList(Map<String, Object> map);
Map<String, String> queryTable(String tableName);
List<Map<String, String>> queryColumns(String tableName);
}
MongoDBGeneratorDao
import com.yongyuankuaile.product.generotor.adaptor.MongoTableInfoAdaptor;
import com.yongyuankuaile.product.generotor.config.MongoCondition;
import com.yongyuankuaile.product.generotor.config.MongoManager;
import com.yongyuankuaile.product.generotor.entity.mongo.MongoDefinition;
import com.yongyuankuaile.product.generotor.factory.MongoDBCollectionFactory;
import com.yongyuankuaile.product.generotor.utils.MongoScanner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author: gxz gongxuanzhang@foxmail.com
**/
@Repository
@Conditional(MongoCondition.class)
public class MongoDBGeneratorDao implements GeneratorDao {
@Autowired
private MongoDBCollectionFactory mongoDBCollectionFactory;
@Override
public List<Map<String, Object>> queryList(Map<String, Object> map) {
List<String> collectionNames = MongoDBCollectionFactory.getCollectionNames(map);
return (List) MongoTableInfoAdaptor.tableInfo(collectionNames);
}
@Override
public Map<String, String> queryTable(String tableName) {
Map<String, String> result = new HashMap<>(4 * 4 / 3 + 1);
result.put("engine", "");
result.put("createTime", "");
result.put("tableComment", "mongoDB " + tableName);
result.put("tableName", tableName);
return result;
}
@Override
public List<Map<String, String>> queryColumns(String tableName) {
MongoDefinition mongoDefinition = MongoManager.getInfo(tableName);
if (mongoDefinition == null) {
System.out.println(tableName);
MongoScanner mongoScanner = new MongoScanner(mongoDBCollectionFactory.getCollection(tableName));
mongoDefinition = mongoScanner.getProduct();
}
return MongoTableInfoAdaptor.columnInfo(mongoDefinition);
}
}
MySQLGeneratorDao
import org.apache.ibatis.annotations.Mapper;
/**
* MySQL代码生成器
*
* @author Mark sunlightcs@gmail.com
* @since 2018-07-24
*/
@Mapper
public interface MySQLGeneratorDao extends GeneratorDao {
}
OracleGeneratorDao
import org.apache.ibatis.annotations.Mapper;
/**
* Oracle代码生成器
*
* @author Mark sunlightcs@gmail.com
* @since 2018-07-24
*/
@Mapper
public interface OracleGeneratorDao extends GeneratorDao {
}
PostgreSQLGeneratorDao
import org.apache.ibatis.annotations.Mapper;
/**
* PostgreSQL代码生成器
*
* @author Mark sunlightcs@gmail.com
* @since 2018-07-24
*/
@Mapper
public interface PostgreSQLGeneratorDao extends GeneratorDao {
}
SQLServerGeneratorDao
import org.apache.ibatis.annotations.Mapper;
/**
* SQLServer代码生成器
*
* @author Mark sunlightcs@gmail.com
* @since 2018-07-24
*/
@Mapper
public interface SQLServerGeneratorDao extends GeneratorDao {
}
对应的xml层
MySQLGeneratorDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yongyuankuaile.product.generotor.dao.MySQLGeneratorDao">
<select id="queryList" resultType="map">
select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables
where table_schema = (select database())
<if test="tableName != null and tableName.trim() != ''">
and table_name like concat('%', #{tableName}, '%')
</if>
order by create_time desc
</select>
<select id="queryTable" resultType="map">
select table_name tableName, engine, table_comment tableComment, create_time createTime from information_schema.tables
where table_schema = (select database()) and table_name = #{tableName}
</select>
<select id="queryColumns" resultType="map">
select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns
where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position
</select>
</mapper>
OracleGeneratorDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yongyuankuaile.product.generotor.dao.OracleGeneratorDao">
<resultMap id="tableMap" type="map">
<result column="TABLENAME" property="tableName"></result>
<result column="TABLECOMMENT" property="tableComment"></result>
<result column="COLUMNNAME" property="columnName"></result>
<result column="DATATYPE" property="dataType"></result>
<result column="COLUMNCOMMENT" property="columnComment"></result>
<result column="COLUMNKEY" property="columnKey"></result>
<result column="EXTRA" property="extra"></result>
<result column="CREATETIME" property="createTime"></result>
</resultMap>
<select id="queryList" resultMap="tableMap">
select dt.table_name tableName,
dtc.comments tableComment,
uo.created createTime
from user_tables dt,
user_tab_comments dtc,
user_objects uo
where dt.table_name = dtc.table_name and dt.table_name = uo.object_name and uo.object_type='TABLE'
<if test="tableName != null and tableName.trim() != ''">
and dt.table_name like concat('%', UPPER(#{tableName}))
</if>
order by uo.CREATED desc
</select>
<select id="queryTable" resultMap="tableMap">
select dt.table_name tableName,dtc.comments tableComment,dt.last_analyzed createTime from user_tables dt,user_tab_comments dtc where dt.table_name=dtc.table_name and dt.table_name = UPPER(#{tableName})
</select>
<select id="queryColumns" resultMap="tableMap">
select temp.column_name columnname,
temp.data_type dataType,
temp.comments columnComment,
case temp.constraint_type when 'P' then 'PRI' when 'C' then 'UNI' else '' end "COLUMNKEY",
'' "EXTRA"
from (
select col.column_id,
col.column_name,
col.data_type,
colc.comments,
uc.constraint_type,
-- 去重
row_number() over (partition by col.column_name order by uc.constraint_type desc) as row_flg
from user_tab_columns col
left join user_col_comments colc
on colc.table_name = col.table_name
and colc.column_name = col.column_name
left join user_cons_columns ucc
on ucc.table_name = col.table_name
and ucc.column_name = col.column_name
left join user_constraints uc
on uc.constraint_name = ucc.constraint_name
where col.table_name = upper(#{tableName})
) temp
where temp.row_flg = 1
order by temp.column_id
</select>
</mapper>
PostgreSQLGeneratorDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yongyuankuaile.product.generotor.dao.PostgreSQLGeneratorDao">
<resultMap id="tableMap" type="map">
<result column="tablename" property="tableName"></result>
<result column="tablecomment" property="tableComment"></result>
<result column="columnname" property="columnName"></result>
<result column="datatype" property="dataType"></result>
<result column="columncomment" property="columnComment"></result>
<result column="columnkey" property="columnKey"></result>
<result column="extra" property="extra"></result>
<result column="createtime" property="createTime"></result>
</resultMap>
<select id="queryList" resultMap="tableMap">
select t1.tablename as tableName, obj_description(relfilenode, 'pg_class') as tableComment, now() as createTime from pg_tables t1, pg_class t2
where t1.tablename not like 'pg%' and t1.tablename not like 'sql_%' and t1.tablename = t2.relname
<if test="tableName != null and tableName.trim() != ''">
and t1.tablename like concat('%', #{tableName}, '%')
</if>
order by t1.tablename desc
</select>
<select id="queryTable" resultMap="tableMap">
select t1.tablename as tableName, obj_description(relfilenode, 'pg_class') as tableComment, now() as createTime from pg_tables t1, pg_class t2
where t1.tablename = #{tableName} and t1.tablename = t2.relname
</select>
<select id="queryColumns" resultMap="tableMap">
select t2.attname as columnName, pg_type.typname as dataType, col_description(t2.attrelid,t2.attnum) as columnComment, '' as extra,
(CASE t3.contype WHEN 'p' THEN 'PRI' ELSE '' END) as columnKey
from pg_class as t1, pg_attribute as t2 inner join pg_type on pg_type.oid = t2.atttypid
left join pg_constraint t3 on t2.attnum = t3.conkey[1] and t2.attrelid = t3.conrelid
where t1.relname = #{tableName} and t2.attrelid = t1.oid and t2.attnum>0
</select>
</mapper>
SQLServerGeneratorDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yongyuankuaile.product.generotor.dao.SQLServerGeneratorDao">
<select id="queryList" resultType="map">
select * from
(
select cast(so.name as nvarchar(500)) as tableName, cast(sep.value as nvarchar(500)) as tableComment, getDate() as createTime
from sysobjects so
left JOIN sys.extended_properties sep
on sep.major_id=so.id and sep.minor_id=0
where (xtype='U' or xtype='v')
) t where 1=1
<if test="tableName != null and tableName.trim() != ''">
and t.tableName like concat('%', #{tableName}, '%')
</if>
order by t.tableName
</select>
<select id="queryTable" resultType="map">
select * from (
select cast(so.name as nvarchar(500)) as tableName, 'mssql' as engine,cast(sep.value as nvarchar(500)) as tableComment, getDate() as createTime
from sysobjects so
left JOIN sys.extended_properties sep on sep.major_id=so.id and sep.minor_id=0
where (xtype='U' or xtype='v')
) t where t.tableName=#{tableName}
</select>
<select id="queryColumns" resultType="map">
SELECT
cast(
b.NAME AS NVARCHAR(500)
) AS columnName,
cast(
sys.types.NAME AS NVARCHAR(500)
) AS dataType,
cast(
c.VALUE AS NVARCHAR(500)
) AS columnComment,
(
SELECT
CASE
count( 1 )
WHEN 1 then 'PRI'
ELSE ''
END
FROM
syscolumns,
sysobjects,
sysindexes,
sysindexkeys,
systypes
WHERE
syscolumns.xusertype = systypes.xusertype
AND syscolumns.id = object_id(A.NAME)
AND sysobjects.xtype = 'PK'
AND sysobjects.parent_obj = syscolumns.id
AND sysindexes.id = syscolumns.id
AND sysobjects.NAME = sysindexes.NAME
AND sysindexkeys.id = syscolumns.id
AND sysindexkeys.indid = sysindexes.indid
AND syscolumns.colid = sysindexkeys.colid
AND syscolumns.NAME = B.NAME
) as columnKey,
'' as extra
FROM
(
select
name,
object_id
from
sys.tables
UNION all select
name,
object_id
from
sys.views
) a
INNER JOIN sys.COLUMNS b ON
b.object_id = a.object_id
LEFT JOIN sys.types ON
b.user_type_id = sys.types.user_type_id
LEFT JOIN sys.extended_properties c ON
c.major_id = b.object_id
AND c.minor_id = b.column_id
WHERE
a.NAME = #{tableName}
and sys.types.NAME != 'sysname'
</select>
</mapper>
config配置类
DbConfig
import com.yongyuankuaile.product.generotor.dao.*;
import com.yongyuankuaile.product.generotor.utils.RRException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* 数据库配置
*
* @author Mark sunlightcs@gmail.com
*/
@Configuration
public class DbConfig {
@Value("${renren.database: mysql}")
private String database;
@Autowired
private MySQLGeneratorDao mySQLGeneratorDao;
@Autowired
private OracleGeneratorDao oracleGeneratorDao;
@Autowired
private SQLServerGeneratorDao sqlServerGeneratorDao;
@Autowired
private PostgreSQLGeneratorDao postgreSQLGeneratorDao;
private static boolean mongo = false;
@Bean
@Primary
@Conditional(MongoNullCondition.class)
public GeneratorDao getGeneratorDao() {
if ("mysql".equalsIgnoreCase(database)) {
return mySQLGeneratorDao;
} else if ("oracle".equalsIgnoreCase(database)) {
return oracleGeneratorDao;
} else if ("sqlserver".equalsIgnoreCase(database)) {
return sqlServerGeneratorDao;
} else if ("postgresql".equalsIgnoreCase(database)) {
return postgreSQLGeneratorDao;
} else {
throw new RRException("不支持当前数据库:" + database);
}
}
@Bean
@Primary
@Conditional(MongoCondition.class)
public GeneratorDao getMongoDBDao(MongoDBGeneratorDao mongoDBGeneratorDao) {
mongo = true;
return mongoDBGeneratorDao;
}
public static boolean isMongo() {
return mongo;
}
}
MongoCondition
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @author: gxz gongxuanzhang@foxmail.com
**/
public class MongoCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String database = context.getEnvironment().getProperty("renren.database");
return "mongodb".equalsIgnoreCase(database);
}
}
MongoConfig
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoDatabase;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* @author: gxz gongxuanzhang@foxmail.com
**/
@Component
@ConfigurationProperties(prefix = "mongodb")
public class MongoConfig {
private String host;
private int port;
private String username;
private String password;
private String dataBase;
private boolean auth;
private String source;
@Bean
@Conditional(MongoCondition.class)
private MongoClient getMongoClient() {
List<ServerAddress> adds = new ArrayList<>();
ServerAddress serverAddress = new ServerAddress(this.host, this.port);
adds.add(serverAddress);
if (this.auth) {
MongoCredential mongoCredential = MongoCredential.
createScramSha1Credential(this.username, this.source, this.password.toCharArray());
MongoClientOptions mongoClientOptions = MongoClientOptions.builder().build();
return new MongoClient(adds, mongoCredential, mongoClientOptions);
}
return new MongoClient(adds);
}
@Bean
@Conditional(MongoCondition.class)
public MongoDatabase getDataBase() {
return getMongoClient().getDatabase(dataBase);
}
public MongoConfig setHost(String host) {
this.host = host;
return this;
}
public MongoConfig setPort(int port) {
this.port = port;
return this;
}
public MongoConfig setUsername(String username) {
this.username = username;
return this;
}
public MongoConfig setPassword(String password) {
this.password = password;
return this;
}
public MongoConfig setDataBase(String dataBase) {
this.dataBase = dataBase;
return this;
}
public MongoConfig setAuth(boolean auth) {
this.auth = auth;
return this;
}
public MongoConfig setSource(String source) {
this.source = source;
return this;
}
}
MongoManager
import com.yongyuankuaile.product.generotor.entity.mongo.MongoDefinition;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author gxz
* @date 2020/5/10 12:05
*/
public class MongoManager {
/***mongo扫描很消耗性能 尤其是子类的封装 使用缓存**/
private static Map<String, MongoDefinition> mongoCache = new ConcurrentHashMap<>();
public static Map<String, MongoDefinition> getCache() {
return mongoCache;
}
public static MongoDefinition getInfo(String tableName) {
return mongoCache.getOrDefault(tableName, null);
}
public static MongoDefinition putInfo(String tableName, MongoDefinition mongoDefinition) {
return mongoCache.put(tableName, mongoDefinition);
}
/**
* 当前配置是否为mongo内容
*/
public static boolean isMongo() {
return DbConfig.isMongo();
}
}
MongoNullCondition
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @author: gxz gongxuanzhang@foxmail.com
**/
public class MongoNullCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String database = context.getEnvironment().getProperty("renren.database");
return !"mongodb".equalsIgnoreCase(database);
}
}
adaptor类
MongoTableInfoAdaptor
import com.yongyuankuaile.product.generotor.entity.mongo.MongoDefinition;
import com.yongyuankuaile.product.generotor.entity.mongo.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* mongo适配器
*
* @author: gxz gongxuanzhang@foxmail.com
**/
public class MongoTableInfoAdaptor {
/**
* 查询表信息的时候 mongo只能获得表名 其他只能手动填写
*
* @param names 表名
*/
public static List<Map<String, String>> tableInfo(List<String> names) {
List<Map<String, String>> result = new ArrayList<>(names.size());
for (String name : names) {
result.add(tableInfo(name));
}
return result;
}
public static Map<String, String> tableInfo(String name) {
Map<String, String> tableInfo = new HashMap<>(4 * 4 / 3 + 1);
tableInfo.put("engine", "mongo无引擎");
tableInfo.put("createTime", "mongo无法查询创建时间");
tableInfo.put("tableComment", "mongo无备注");
tableInfo.put("tableName", name);
return tableInfo;
}
/**
* 在查询列名的时候 需要将解析出的mongo信息适配成关系型数据库所需要的信息形式
* 此方法只针对主Bean
*/
public static List<Map<String, String>> columnInfo(MongoDefinition mongoDefinition) {
List<MongoDefinition> child = mongoDefinition.getChild();
List<Map<String, String>> result = new ArrayList<>(child.size());
final String mongoKey = "_id";
for (MongoDefinition definition : child) {
Map<String, String> map = new HashMap<>(5 * 4 / 3 + 1);
String type = Type.typeInfo(definition.getType());
String propertyName = definition.getPropertyName();
String extra = definition.isArray() ? "array" : "";
map.put("extra", extra);
map.put("columnComment", "");
map.put("dataType", definition.hasChild() ? propertyName : type);
map.put("columnName", propertyName);
// mongo默认主键是_id
String columnKey = propertyName.equals(mongoKey) ? "PRI" : "";
map.put("columnKey", columnKey);
result.add(map);
}
return result;
}
}
factory类
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import com.yongyuankuaile.product.generotor.config.MongoCondition;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author: gxz gongxuanzhang@foxmail.com
**/
@Component
@Conditional(MongoCondition.class)
public class MongoDBCollectionFactory {
private static final String TABLE_NAME_KEY = "tableName";
private static final String LIMIT_KEY = "limit";
private static final String OFFSET_KEY = "offset";
private static MongoDatabase mongoDatabase;
// 此处是为了兼容mongo相关内容和关系型数据库的静态耦合所导致的问题
@Autowired
private MongoDatabase database;
@PostConstruct
public void initMongoDatabase(){
mongoDatabase = database;
}
/***
* 通过表名获得查询对象
* @author gxz
* @date 2020/5/9
* @param collectionName mongo的集合名(表名)
* @return 连接查询对象
**/
public MongoCollection<Document> getCollection(String collectionName) {
return mongoDatabase.getCollection(collectionName);
}
/***
* 获得当前数据库的集合名称
* 注: mongo相对关系型数据库较为特殊,查询表名无法分页,用stream实现
* @author gxz
* @date 2020/5/9
* @param map 这是查询条件 和关系型数据库一致
* @return 集合名称
**/
public static List<String> getCollectionNames(Map<String, Object> map) {
int limit = Integer.valueOf(map.get(LIMIT_KEY).toString());
int skip = Integer.valueOf(map.get(OFFSET_KEY).toString());
List<String> names;
if (map.containsKey(TABLE_NAME_KEY)) {
names = getCollectionNames(map.get(TABLE_NAME_KEY).toString());
} else {
names = getCollectionNames();
}
return names.stream().skip(skip).limit(limit).collect(Collectors.toList());
}
/***
* 获得集合名称总数(表的数量) 为了适配MyBatisPlus的分页插件 提供方法
* @author gxz
* @date 2020/5/9
* @param map 这是查询条件 和关系型数据库一致
* @return int
**/
public static int getCollectionTotal(Map<String, Object> map) {
if (map.containsKey(TABLE_NAME_KEY)) {
return getCollectionNames(map.get(TABLE_NAME_KEY).toString()).size();
}
return getCollectionNames().size();
}
private static List<String> getCollectionNames() {
MongoIterable<String> names = mongoDatabase.listCollectionNames();
List<String> result = new ArrayList<>();
for (String name : names) {
result.add(name);
}
return result;
}
private static List<String> getCollectionNames(String likeName) {
return getCollectionNames()
.stream()
.filter((name) -> name.contains(likeName)).collect(Collectors.toList());
}
}
applaction.yml
server:
port: 5000
spring:
# mvc:
# view:
# prefix: /pages/
# suffix: .html
datasource:
name: druidDataSource
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://IP地址:端口号/数据库?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
username: 账号
password: 密码
filters: stat,wall,slf4j,config #配置监控统计拦截的filters,去掉后监控界面SQL无法进行统计,wall用于防火墙。
max-active: 100 #最大连接数
initial-size: 1 #初始化大小
max-wait: 60000 #获取连接等待超时时间
min-idle: 1 #最小连接数
time-between-eviction-runs-millis: 60000 #间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒。
min-evictable-idle-time-millis: 300000 #一个连接在池中最小生存的时间,单位是毫秒。
validation-query: select 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
web:
resources:
static-locations: classpath:/static/,classpath:/views/
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
logging:
config: classpath:logback.xml
#mongodb:
# host: localhost
# port: 27017
# auth: false #是否使用密码验证
# username: tincery
# password: renren
# source: 123456
# database: test
mybatis-plus:
mapperLocations: classpath:mapper/**/*.xml
pagehelper:
reasonable: true
supportMethodsArguments: true
params: count=countSql
#指定数据库,可选值有【mysql、oracle、sqlserver、postgresql、mongodb】
renren:
database: mysql
接下来就是页面模板和前端页面
页面模板是固定的前端是用js和html编写成的
页面模板
add-or-update.vue.vm
<template>
<el-dialog
:title="!dataForm.${pk.attrname} ? '新增' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible">
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="80px">
#foreach($column in $columns)
#if($column.columnName != $pk.columnName)
<el-form-item label="${column.comments}" prop="${column.attrname}">
<el-input v-model="dataForm.${column.attrname}" placeholder="${column.comments}"></el-input>
</el-form-item>
#end
#end
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataFormSubmit()">确定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
data () {
return {
visible: false,
dataForm: {
#foreach($column in $columns)
#if($column.columnName == $pk.columnName)
${column.attrname}: 0,
#else
${column.attrname}: ''#if($velocityCount != $columns.size()),#end
#end
#end
},
dataRule: {
#foreach($column in $columns)
#if($column.columnName != $pk.columnName)
${column.attrname}: [
{ required: true, message: '${column.comments}不能为空', trigger: 'blur' }
]#if($velocityCount != $columns.size()),#end
#end
#end
}
}
},
methods: {
init (id) {
this.dataForm.${pk.attrname} = id || 0
this.visible = true
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
if (this.dataForm.${pk.attrname}) {
this.$http({
url: #[[this.$http.adornUrl]]#(`/${moduleName}/${pathName}/info/#[[$]]#{this.dataForm.${pk.attrname}}`),
method: 'get',
#[[params: this.$http.adornParams()]]#
}).then(({data}) => {
if (data && data.code === 0) {
#foreach($column in $columns)
#if($column.columnName != $pk.columnName)
this.dataForm.${column.attrname} = data.${classname}.${column.attrname}
#end
#end
}
})
}
})
},
// 表单提交
dataFormSubmit () {
#[[this.$refs['dataForm'].validate((valid) => {]]#
if (valid) {
this.$http({
url: #[[this.$http.adornUrl]]#(`/${moduleName}/${pathName}/${!this.dataForm.${pk.attrname} ? 'save' : 'update'}`),
method: 'post',
#[[data: this.$http.adornData({]]#
#foreach($column in $columns)
#if($column.columnName == $pk.columnName)
'${column.attrname}': this.dataForm.${column.attrname} || undefined,
#else
'${column.attrname}': this.dataForm.${column.attrname}#if($velocityCount != $columns.size()),#end
#end
#end
})
}).then(({data}) => {
if (data && data.code === 0) {
#[[this.$message({]]#
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.visible = false
#[[this.$emit('refreshDataList')]]#
}
})
} else {
#[[this.$message.error(data.msg)]]#
}
})
}
})
}
}
}
</script>
Controller.java.vm
package ${package}.${moduleName}.controller;
import java.util.Arrays;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.github.pagehelper.PageInfo;
import ${package}.${moduleName}.entity.${className}Entity;
import ${package}.${moduleName}.service.${className}Service;
import ${mainPath}.common.utils.PageUtils;
import ${mainPath}.common.utils.R;
import io.swagger.annotations.Api;
/**
* ${comments}
*
* @author ${author}
* @email ${email}
* @date ${datetime}
*/
@RestController
@RequestMapping("${moduleName}/${pathName}")
@Api(tags = {"${comments}模块"}, description = "${comments}")
public class ${className}Controller {
@Autowired
private ${className}Service ${classname}Service;
/**
* 使用Mybatis-plus自带分页操作 并对deptVO进行条件构造
*/
@PostMapping("/list")
@ApiOperation(value = "分页查询", notes = "分页查询",response = ${className}Entity.class)
public R list(@RequestBody(required = false) ${className}Entity ${classname}) {
PageInfo page = ${classname}Service.PageQuery(${classname});
return R.ok(page);
}
/**
* 信息
*/
@GetMapping("/info/{${pk.attrname}}")
public R info(@PathVariable("${pk.attrname}") ${pk.attrType} ${pk.attrname}){
${className}Entity ${classname} = ${classname}Service.getById(${pk.attrname});
return R.ok( ${classname});
}
/**
* 保存
*/
@PostMapping("/save")
@ApiOperation(value = "保存", notes = "保存时,ID由数据库生成,无需填写,有则忽略", tags = "保存")
public R save(@RequestBody ${className}Entity ${classname}){
${classname}Service.save(${classname});
return R.ok();
}
/**
* 修改
*/
@PostMapping("/update")
@ApiOperation(value = "更新", notes = "id必填,其它属性存在则更新,否则忽略", tags = "更新")
public R update(@RequestBody ${className}Entity ${classname}){
${classname}Service.updateById(${classname});
return R.ok();
}
/**
* 删除
*/
@GetMapping("/delete")
@ApiOperation(value = "删除", notes = "删除后无法恢复", tags = "删除")
public R delete(@RequestBody ${pk.attrType}[] ${pk.attrname}s){
${classname}Service.removeByIds(Arrays.asList(${pk.attrname}s));
return R.ok();
}
}
Dao.java.vm
package ${package}.${moduleName}.dao;
import ${package}.${moduleName}.entity.${className}Entity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* ${comments}
*
* @author ${author}
* @email ${email}
* @date ${datetime}
*/
@Mapper
public interface ${className}Dao extends BaseMapper<${className}Entity> {
}
Dao.xml.vm
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package}.${moduleName}.dao.${className}Dao">
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="${package}.${moduleName}.entity.${className}Entity" id="${classname}Map">
#foreach($column in $columns)
<result property="${column.attrname}" column="${column.columnName}"/>
#end
</resultMap>
</mapper>
Entity.java.vm
package ${package}.${moduleName}.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import ${package}.${moduleName}.common.QueryVo;
#if(${hasBigDecimal})
import java.math.BigDecimal;
#end
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import io.swagger.annotations.ApiModelProperty;
/**
* ${comments}
*
* @author ${author}
* @email ${email}
* @date ${datetime}
*/
@Data
@TableName("${tableName}")
@ApiModel("${comments}")
public class ${className}Entity implements Serializable {
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
/**
* $column.comments
*/
@ApiModelProperty("$column.comments")
#if($column.columnName == $pk.columnName)
@TableId
#end
private $column.attrType $column.attrname;
#end
//当前页面
@TableField(exist = false)
private Integer current;
//每页条数
@TableField(exist = false)
private Integer size;
}
}
index.vue.vm
<template>
<div class="mod-config">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()">查询</el-button>
<el-button v-if="isAuth('${moduleName}:${pathName}:save')" type="primary" @click="addOrUpdateHandle()">新增</el-button>
<el-button v-if="isAuth('${moduleName}:${pathName}:delete')" type="danger" @click="deleteHandle()" :disabled="dataListSelections.length <= 0">批量删除</el-button>
</el-form-item>
</el-form>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;">
<el-table-column
type="selection"
header-align="center"
align="center"
width="50">
</el-table-column>
#foreach($column in $columns)
<el-table-column
prop="${column.attrname}"
header-align="center"
align="center"
label="${column.comments}">
</el-table-column>
#end
<el-table-column
fixed="right"
header-align="center"
align="center"
width="150"
label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.${pk.attrname})">修改</el-button>
<el-button type="text" size="small" @click="deleteHandle(scope.row.${pk.attrname})">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
</div>
</template>
<script>
import AddOrUpdate from './${pathName}-add-or-update'
export default {
data () {
return {
dataForm: {
key: ''
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false
}
},
components: {
AddOrUpdate
},
activated () {
this.getDataList()
},
methods: {
// 获取数据列表
getDataList () {
this.dataListLoading = true
#[[this.$http({]]#
#[[url: this.$http.adornUrl]]#('/${moduleName}/${pathName}/list'),
method: 'get',
#[[params: this.$http.adornParams({]]#
'page': this.pageIndex,
'limit': this.pageSize,
'key': this.dataForm.key
})
}).then(({data}) => {
if (data && data.code === 0) {
this.dataList = data.page.list
this.totalPage = data.page.totalCount
} else {
this.dataList = []
this.totalPage = 0
}
this.dataListLoading = false
})
},
// 每页数
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
// 当前页
currentChangeHandle (val) {
this.pageIndex = val
this.getDataList()
},
// 多选
selectionChangeHandle (val) {
this.dataListSelections = val
},
// 新增 / 修改
addOrUpdateHandle (id) {
this.addOrUpdateVisible = true
#[[this.$nextTick(() => {]]#
this.$refs.addOrUpdate.init(id)
})
},
// 删除
deleteHandle (id) {
var ids = id ? [id] : this.dataListSelections.map(item => {
return item.${pk.attrname}
})
#[[this.$confirm(`确定对[id=${ids.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {]]#
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
#[[this.$http({]]#
url: #[[this.$http.adornUrl]]#('/${moduleName}/${pathName}/delete'),
method: 'post',
data: this.$http.adornData(ids, false)
}).then(({data}) => {
if (data && data.code === 0) {
#[[this.$message({]]#
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getDataList()
}
})
} else {
#[[this.$message.error(data.msg)]]#
}
})
})
}
}
}
</script>
menu.sql.vm
-- 菜单SQL
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
VALUES ('1', '${comments}', '${moduleName}/${pathName}', NULL, '1', 'config', '6');
-- 按钮父菜单ID
set @parentId = @@identity;
-- 菜单对应按钮SQL
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '查看', null, '${moduleName}:${pathName}:list,${moduleName}:${pathName}:info', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '新增', null, '${moduleName}:${pathName}:save', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '修改', null, '${moduleName}:${pathName}:update', '2', null, '6';
INSERT INTO `sys_menu` (`parent_id`, `name`, `url`, `perms`, `type`, `icon`, `order_num`)
SELECT @parentId, '删除', null, '${moduleName}:${pathName}:delete', '2', null, '6';
MongoChildrenEntity.java.vm
package ${package}.${moduleName}.entity;
#if(${hasList})
import java.util.List;
#end
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.annotation.Id;
/**
* ${comments}
*
* @author ${author}
* @email ${email}
* @date ${datetime}
*/
@Data
public class ${className}InnerEntity {
#foreach ($column in $columns)
private #if($column.extra == "array")List<#end$column.attrType#if($column.extra == "array")>#end $column.attrname;
#end
}
MongoEntity.java.vm
package ${package}.${moduleName}.entity;
#if(${hasBigDecimal})
import java.math.BigDecimal;
#end
#if(${hasList})
import java.util.List;
#end
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.annotation.Id;
/**
* ${comments}
*
* @author ${author}
* @email ${email}
* @date ${datetime}
*/
@Data
@Document(collection = "${tableName}")
public class ${className}Entity implements Serializable {
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
#if($column.columnName == "id")
@Id
#end
private #if($column.extra == "array")List<#end$column.attrType#if($column.extra == "array")>#end $column.attrname;
#end
}
Service.java.vm
package ${package}.${moduleName}.service;
import com.baomidou.mybatisplus.extension.service.IService;
import ${package}.${moduleName}.entity.${className}Entity;
import com.github.pagehelper.PageInfo;
import java.util.Map;
/**
* ${comments}
*
* @author ${author}
* @email ${email}
* @date ${datetime}
*/
public interface ${className}Service extends IService<${className}Entity> {
PageInfo PageQuery(${className}Entity ${classname});
}
ServiceImpl.java.vm
package ${package}.${moduleName}.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ${mainPath}.common.PageUtils;
import ${mainPath}.common.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ${package}.${moduleName}.dao.${className}Dao;
import ${package}.${moduleName}.entity.${className}Entity;
import ${package}.${moduleName}.service.${className}Service;
@Service("${classname}Service")
public class ${className}ServiceImpl extends ServiceImpl<${className}Dao, ${className}Entity> implements ${className}Service {
@Autowired
${className}Dao ${classname}dao;
@Override
public PageInfo PageQuery(${className}Entity ${classname}) {
QueryWrapper<${className}Entity> queryWrapper = new QueryWrapper<>();
//开启分页功能
PageHelper.startPage(${classname}.getCurrent(), ${classname}.getSize());
//查所有数据返回
PageInfo pageInfo = new PageInfo(${classname}dao.selectList(queryWrapper));
return pageInfo;
}
}
generator.properties
#路径
mainPath=com.yongyuankuaile.product
#包路径
package=com.yongyuankuaile.product
#模块名称
moduleName=sys
#用户名
author=zy
#邮箱
email=111111111@163.com
#路径
tablePrefix=tb_
#泛型
tinyint=Integer
smallint=Integer
mediumint=Integer
int=Integer
integer=Integer
bigint=Long
float=Float
double=Double
decimal=BigDecimal
bit=Boolean
char=String
varchar=String
tinytext=String
text=String
mediumtext=String
longtext=String
date=Date
datetime=Date
timestamp=Date
NUMBER=Integer
INT=Integer
INTEGER=Integer
BINARY_INTEGER=Integer
LONG=String
FLOAT=Float
BINARY_FLOAT=Float
DOUBLE=Double
BINARY_DOUBLE=Double
DECIMAL=BigDecimal
CHAR=String
VARCHAR=String
VARCHAR2=String
NVARCHAR=String
NVARCHAR2=String
CLOB=String
BLOB=String
DATE=Date
DATETIME=Date
TIMESTAMP=Date
TIMESTAMP(6)=Date
int8=Long
int4=Integer
int2=Integer
numeric=BigDecimal
nvarchar=String