Commit ac23435e by gxz

增加了Mongo逆向工程

原理是扫描mongo的表记录  利用mongo的$type查询关键字查询
添加了一些有关mongo的内容
因为mongo和关系型数据库有诸多不同,许多内容不能兼容  修改了一些原先存在的类非常抱歉
parent d1face53
......@@ -29,6 +29,7 @@
<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>
<dependencies>
......@@ -120,6 +121,12 @@
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- mongo驱动 -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo.version}</version>
</dependency>
</dependencies>
<build>
......
package io.renren.adaptor;
import io.renren.entity.mongo.MongoDefinition;
import io.renren.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;
}
}
......@@ -33,7 +33,10 @@ public class DbConfig {
private SQLServerGeneratorDao sqlServerGeneratorDao;
@Autowired
private PostgreSQLGeneratorDao postgreSQLGeneratorDao;
@Autowired
private MongoDBGeneratorDao mongoDBGeneratorDao;
private static boolean mongo = false;
@Bean
@Primary
public GeneratorDao getGeneratorDao(){
......@@ -45,8 +48,16 @@ public class DbConfig {
return sqlServerGeneratorDao;
}else if("postgresql".equalsIgnoreCase(database)){
return postgreSQLGeneratorDao;
}else {
}else if("mongodb".equalsIgnoreCase(database)){
mongo = true;
return mongoDBGeneratorDao;
}
else {
throw new RRException("不支持当前数据库:" + database);
}
}
public static boolean isMongo(){
return mongo;
}
}
package io.renren.config;
import org.apache.commons.lang.StringUtils;
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 mongodb = context.getEnvironment().getProperty("mongodb.host");
return StringUtils.isNotEmpty(mongodb);
}
}
package io.renren.config;
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
**/
@Conditional(MongoCondition.class)
@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
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
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;
}
}
package io.renren.config;
import io.renren.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();
}
}
package io.renren.dao;
import io.renren.adaptor.MongoTableInfoAdaptor;
import io.renren.config.MongoManager;
import io.renren.entity.mongo.MongoDefinition;
import io.renren.factory.MongoDBCollectionFactory;
import io.renren.utils.MongoScanner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author: gxz gongxuanzhang@foxmail.com
**/
@Repository
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);
}
}
package io.renren.entity.mongo;
import io.renren.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;
}
}
package io.renren.entity.mongo;
import io.renren.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;
}
}
package io.renren.entity.mongo;
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;
}
}
package io.renren.factory;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author: gxz gongxuanzhang@foxmail.com
**/
@Component
public class MongoDBCollectionFactory {
private final String TABLE_NAME_KEY = "tableName";
private final String LIMIT_KEY = "limit";
private final String OFFSET_KEY = "offset";
@Autowired
private MongoDatabase mongoDatabase;
/***
* 通过表名获得查询对象
* @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 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 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 List<String> getCollectionNames() {
MongoIterable<String> names = mongoDatabase.listCollectionNames();
List<String> result = new ArrayList<>();
for (String name : names) {
result.add(name);
}
return result;
}
private List<String> getCollectionNames(String likeName) {
return getCollectionNames()
.stream()
.filter((name) -> name.contains(likeName)).collect(Collectors.toList());
}
}
......@@ -10,7 +10,11 @@ package io.renren.service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.renren.config.MongoManager;
import io.renren.dao.GeneratorDao;
import io.renren.dao.MongoDBGeneratorDao;
import io.renren.entity.mongo.MongoDefinition;
import io.renren.factory.MongoDBCollectionFactory;
import io.renren.utils.GenUtils;
import io.renren.utils.PageUtils;
import io.renren.utils.Query;
......@@ -32,12 +36,17 @@ import java.util.zip.ZipOutputStream;
public class SysGeneratorService {
@Autowired
private GeneratorDao generatorDao;
@Autowired
private MongoDBCollectionFactory mongoDBCollectionFactory;
public PageUtils queryList(Query query) {
Page<?> page = PageHelper.startPage(query.getPage(), query.getLimit());
List<Map<String, Object>> list = generatorDao.queryList(query);
return new PageUtils(list, (int)page.getTotal(), query.getLimit(), query.getPage());
int total = (int) page.getTotal();
if(generatorDao instanceof MongoDBGeneratorDao){
total = mongoDBCollectionFactory.getCollectionTotal(query);
}
return new PageUtils(list, total, query.getLimit(), query.getPage());
}
public Map<String, String> queryTable(String tableName) {
......@@ -48,10 +57,11 @@ public class SysGeneratorService {
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);
......@@ -60,6 +70,12 @@ public class SysGeneratorService {
//生成代码
GenUtils.generatorCode(table, columns, zip);
}
if(MongoManager.isMongo()){
GenUtils.generatorMongoCode(tableNames, zip);
}
IOUtils.closeQuietly(zip);
return outputStream.toByteArray();
}
......
......@@ -7,8 +7,8 @@ spring:
type: com.alibaba.druid.pool.DruidDataSource
#MySQL配置
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/renren_fast?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: renren
url: jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
#oracle配置
# driverClassName: oracle.jdbc.OracleDriver
......@@ -25,12 +25,23 @@ spring:
# url: jdbc:postgresql://192.168.10.10:5432/renren_fast
# username: postgres
# password: 123456
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
resources:
static-locations: classpath:/static/,classpath:/views/
mongodb:
host: localhost
port: 27017
auth: false #是否使用密码验证
username: tincery
password: Txy123.com
source: tincery_pro
database: tincery_pro
mybatis-plus:
mapperLocations: classpath:mapper/**/*.xml
......@@ -42,7 +53,7 @@ pagehelper:
params: count=countSql
#指定数据库,可选值有【mysql、oracle、sqlserver、postgresql】
#指定数据库,可选值有【mysql、oracle、sqlserver、postgresql、mongodb
renren:
database: mysql
database: mongodb
......@@ -30,6 +30,7 @@ text=String
mediumtext=String
longtext=String
date=Date
datetime=Date
timestamp=Date
......
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
}
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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment