提交 fc0e1bc1 编写于 作者: sq3536's avatar sq3536

提交

上级 2bf598b3
package cn.ibizlab.core.extensions.service;
import cn.ibizlab.core.lite.domain.DstDataSource;
import cn.ibizlab.util.helper.Setting;
import cn.ibizlab.core.lite.extensions.domain.SysModel;
import cn.ibizlab.core.lite.extensions.service.LiteCoreService;
import cn.ibizlab.core.lite.service.DstLiquibaseService;
import cn.ibizlab.core.lite.service.impl.DstDataSourceServiceImpl;
import cn.ibizlab.util.domain.LiquibaseProp;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.helper.Setting;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import cn.ibizlab.core.lite.domain.DstDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Primary;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.*;
/**
* 实体[数据源] 自定义服务对象
......@@ -32,6 +39,12 @@ public class DstDataSourceExService extends DstDataSourceServiceImpl {
protected Class currentModelClass() {
return com.baomidou.mybatisplus.core.toolkit.ReflectionKit.getSuperClassGenericType(this.getClass().getSuperclass(), 1);
}
@Resource
public LiteCoreService liteCoreService;
@Resource
public DstLiquibaseService dstLiquibaseService;
/**
* [BuildDS:buildDS] 行为扩展
......@@ -135,5 +148,50 @@ public class DstDataSourceExService extends DstDataSourceServiceImpl {
return true;
}
@Override
@Transactional
public DstDataSource initDS(DstDataSource et) {
DstDataSource ds = getById(et.getDsId());
if(ObjectUtils.isEmpty(ds)){
throw new BadRequestAlertException("数据源不存在,请检查是否填写正确","","ibzInit");
}
buildDS(ds);
String datasourceMessage = ds.getDsCfg();
if(ObjectUtils.isEmpty(datasourceMessage)){
throw new BadRequestAlertException("数据源不能为空","","ibzInit");
}
List<Setting> settings = JSONArray.parseArray(ds.getDsCfg(), Setting.class);
Map datasourceMap = new HashMap();
settings.forEach(setting -> datasourceMap.put(setting.getProperty(),setting.getValue()));
if(ObjectUtils.isEmpty(datasourceMap.get("username"))){
throw new BadRequestAlertException("数据源用户名不能为空","","ibzInit");
}
if(ObjectUtils.isEmpty(datasourceMap.get("password"))){
throw new BadRequestAlertException("数据源密码不能为空","","ibzInit");
}
if(ObjectUtils.isEmpty(datasourceMap.get("url"))){
throw new BadRequestAlertException("数据源地址不能为空","","ibzInit");
}
if(ObjectUtils.isEmpty(datasourceMap.get("defaultSchema"))){
throw new BadRequestAlertException("数据源默认数据库不能为空","","ibzInit");
}
if(ObjectUtils.isEmpty(datasourceMap.get("defaultSystemId"))){
throw new BadRequestAlertException("逆向工程归属系统为空","","ibzInit");
}
LiquibaseProp lp = new LiquibaseProp();
lp.setUsername(datasourceMap.get("username").toString());
lp.setPassword(datasourceMap.get("password").toString());
lp.setUrl(datasourceMap.get("url").toString());
lp.setDefaultSchema(datasourceMap.get("defaultSchema").toString());
// 调用liquibase逆向工程的逻辑,生成一个xml,并返回一个SysModel对象
SysModel sysModel = dstLiquibaseService.generateLiquibase(lp,datasourceMap.get("defaultSystemId").toString());
liteCoreService.syncSysModel(sysModel,1);
return et;
}
}
package cn.ibizlab.core.lite.service;
import cn.ibizlab.core.lite.domain.MetaField;
import cn.ibizlab.core.lite.domain.MetaRelationship;
import cn.ibizlab.core.lite.extensions.domain.MetaEntityModel;
import cn.ibizlab.core.lite.extensions.domain.SysModel;
import cn.ibizlab.core.util.config.LiquibaseConfiguration;
import cn.ibizlab.util.domain.LiquibaseProp;
import com.alibaba.fastjson.JSON;
import liquibase.Liquibase;
import liquibase.database.Database;
import liquibase.database.DatabaseConnection;
import liquibase.database.DatabaseFactory;
import liquibase.database.OfflineConnection;
import liquibase.database.jvm.JdbcConnection;
import liquibase.diff.output.DiffOutputControl;
import liquibase.exception.DatabaseException;
import liquibase.integration.commandline.CommandLineUtils;
import liquibase.integration.spring.SpringLiquibase;
import liquibase.resource.ResourceAccessor;
import liquibase.util.StringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.json.JSONObject;
import org.json.XML;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@Slf4j
@Service("DstLiquibaseService")
public class DstLiquibaseService{
private boolean ignoreClasspathPrefix = true;
protected String contexts;
protected Map<String, String> parameters;
protected String defaultSchema;
protected String liquibaseSchema;
protected String databaseChangeLogTable;
protected String databaseChangeLogLockTable;
protected String liquibaseTablespace;
protected boolean dropFirst;
@Value("${ibiz.filePath:/app/file/}")
protected String liquibasePath;
@Value("${ibiz.generateDs.catalogName:}")
protected String catalogName;
@Value("${ibiz.generateDs.generateField:tables,columns,indexes,foreignkeys,primarykeys,uniqueconstraints}")
protected String generateField;
@Value("${ibiz.generateDs.includeCatalog:false}")
protected Boolean includeCatalog;
@Value("${ibiz.generateDs.includeSchema:false}")
private boolean includeSchema;
@Value("${ibiz.generateDs.includeTablespace:true}")
private boolean includeTablespace;
@Value("${ibiz.generateDs.context:}")
private String context;
@Value("${ibiz.generateDs.dataDir:}")
private String dataDir;
@Resource
public LiquibaseConfiguration liquibaseConfiguration;
public SysModel generateLiquibase(LiquibaseProp liquibaseProp, String name) {
SysModel sysModel = liquibaseGenerateChangeLog(liquibaseProp,name);
return sysModel;
}
@SneakyThrows
public SysModel liquibaseGenerateChangeLog(LiquibaseProp liquibaseProp,String name){
// 根据指定数据源生成对象
String liquibaseChangeLogPath = getChangeLog();
SpringLiquibase springLiquibase = liquibaseConfiguration.masterliquibase(liquibaseProp);
Liquibase liquibase = createLiquibase(springLiquibase,liquibaseChangeLogPath);
Database database = liquibase.getDatabase();
File file = new File(liquibaseChangeLogPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(!file.exists()){
file.createNewFile();
}
DiffOutputControl diffOutputControl = new DiffOutputControl(includeCatalog, includeSchema, includeTablespace, null);
CommandLineUtils.doGenerateChangeLog(liquibaseChangeLogPath, database, catalogName,liquibaseProp.getDefaultSchema(),StringUtils.trimToNull(generateField),
name, context, dataDir, diffOutputControl);
SysModel sysModel = generateSysModel(liquibaseChangeLogPath);
return sysModel;
}
/**
* 构建一个SysModel对象
* @param path 生成liquibaseChangeLog路径
*/
public static SysModel generateSysModel(String path) {
List<MetaEntityModel> metaEntityModels = new CopyOnWriteArrayList<>();
SysModel sysModel = new SysModel();
Map<String, MetaRelationship> parentMap = null;
Map<String, MetaRelationship> subMap = null;
List<Map<String,MetaRelationship>> parentEntities = null;
List<Map<String,MetaRelationship>> subEntities = null;
MetaRelationship parent = null;
MetaRelationship sub = null;
MetaEntityModel metaEntityModel = null;
List<Map> commonMessage = null;
MetaField metaField = null;
List<Map> column = null;
Map head = null;
Map temp = null;
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(ConvertXMLtoJSON(path));
head = (Map) jsonObject.get("databaseChangeLog");
commonMessage = (List<Map>) head.get("changeSet");
parentEntities = new CopyOnWriteArrayList<>();
subEntities = new CopyOnWriteArrayList<>();
// 维护父子键实体
for (int i = 0;i < commonMessage.size(); i++) {
temp = (Map) commonMessage.get(i).get("addForeignKeyConstraint");
if(!ObjectUtils.isEmpty(temp)){
// 存入父键map
parent = new MetaRelationship();
parentMap = new ConcurrentHashMap();
parent.setName("DER1N_"+temp.get("referencedTableName").toString().toUpperCase());
parent.setCodeName(temp.get("referencedColumnNames").toString());
parent.setEntityName(temp.get("referencedTableName").toString().toUpperCase());
parent.setRelationType("DER1N");
parent.setSystemId(commonMessage.get(0).get("author").toString());
parent.setRefEntityName(temp.get("baseTableName").toString().toUpperCase());
parentMap.put(temp.get("baseColumnNames").toString(),parent);
parentEntities.add(parentMap);
// 存入子键map
sub = new MetaRelationship();
subMap = new ConcurrentHashMap();
sub.setName("DER1N_"+temp.get("baseTableName").toString().toUpperCase());
sub.setCodeName(temp.get("baseColumnNames").toString());
sub.setEntityName(temp.get("baseTableName").toString().toUpperCase());
sub.setRelationType("DER1N");
sub.setSystemId(commonMessage.get(0).get("author").toString());
sub.setRefEntityName(temp.get("referencedTableName").toString().toUpperCase());
subMap.put(temp.get("referencedColumnNames").toString(),sub);
subEntities.add(subMap);
}
}
// 第一、二层 获取第一个作者以及id
if (!ObjectUtils.isEmpty(commonMessage)){
sysModel.setSystemid((String) commonMessage.get(0).get("author"));
sysModel.setSystemname((String) commonMessage.get(0).get("author"));
}
Hashtable<String,Set<String>> keysets=new Hashtable<String,Set<String>>();
for (int i = 0;i < commonMessage.size(); i++) {
temp = (Map) commonMessage.get(i).get("addPrimaryKey");
if(ObjectUtils.isEmpty(temp)){
continue;
}
if(ObjectUtils.isEmpty(temp.get("tableName"))||ObjectUtils.isEmpty(temp.get("columnNames"))){
continue;
}
String tableName=temp.get("tableName").toString().toUpperCase();
String columnNames=temp.get("columnNames").toString().toUpperCase().replace(" ", "");
Set<String> sets=new LinkedHashSet<>();
for(String str:columnNames.split(","))
{
sets.add(str);
}
keysets.put(tableName, sets);
}
// 第三层 获取实体对象List 在这层可以放入subEntitys、parentEntitys等关系字段
for (int i = 0;i < commonMessage.size(); i++) {
temp = (Map) commonMessage.get(i).get("createTable");
if(ObjectUtils.isEmpty(temp)){
continue;
}
metaEntityModel = new MetaEntityModel();
// 为了获取MetaEntityModel下那些基本类型字段(此处可补充MetaEntityModel等描述字段)
String tableName=temp.get("tableName") == null ? "" : temp.get("tableName").toString().toUpperCase();
metaEntityModel.setEntityName(tableName);
metaEntityModel.setCodeName(tableName);
metaEntityModel.setTableName(tableName);
metaEntityModel.setLogicName(temp.get("remarks") == null ? metaEntityModel.getEntityName() : temp.get("remarks").toString().toUpperCase());
metaEntityModel.setSystemId((String) commonMessage.get(0).get("author"));
if(!(temp.get("column") instanceof List))
continue;
column = (List<Map>) temp.get("column");
// 属性List
List<MetaField> metaFields = new CopyOnWriteArrayList<>();
List<MetaRelationship> parentRelationships = new CopyOnWriteArrayList<>();
List<MetaRelationship> subRelationships = new CopyOnWriteArrayList<>();
List<MetaField> unionKeys=new ArrayList<>();
Set<String> keyset=keysets.get(tableName);
if(keyset==null){
keyset = new LinkedHashSet<>();
}
for (int j = 0; j < column.size();j++){
// (此处可补充MetaField描述字段,以及父子外键关系等)
metaField = new MetaField();
metaField.setFieldName(column.get(j).get("name") == null? "" : column.get(j).get("name").toString().toUpperCase());
metaField.setCodeName(metaField.getFieldName());
String logicName=column.get(j).get("remarks") == null? metaField.getFieldName() : column.get(j).get("remarks").toString().trim().replace("\n","");
if(logicName.length()>30)
logicName=logicName.substring(0,30);
metaField.setFieldLogicName(logicName);
metaField.setDataType(column.get(j).get("type") == null? "" : fieldToName(column.get(j).get("type").toString().toUpperCase()));
int[] len=fieldToLength(column.get(j).get("type").toString());
metaField.setDataLength(column.get(j).get("type") == null? 0 : len[0]);
if(len[1]>0)
metaField.setDataPreci(len[1]);
if(metaField.getDataType().indexOf("CHAR")>=0) {
metaField.setFieldType("TEXT");
if(metaField.getDataLength()>=1000)
metaField.setFieldType("LONGTEXT_1000");
}
else if((metaField.getDataType().indexOf("NUMB")>=0&&(metaField.getDataPreci()==null||metaField.getDataPreci()==0)&&metaField.getDataLength()>9)||(metaField.getDataType().indexOf("BIGINT")>=0)||(metaField.getDataType().indexOf("LONG")>=0))
metaField.setFieldType("BIGINT");
else if((metaField.getDataType().indexOf("NUMB")>=0&&(metaField.getDataPreci()==null||metaField.getDataPreci()==0))||(metaField.getDataType().indexOf("INT")>=0))
metaField.setFieldType("INT");
else if(metaField.getDataType().indexOf("NUMB")>=0||metaField.getDataType().indexOf("DECIMAL")>=0||metaField.getDataType().indexOf("FLOAT")>=0)
metaField.setFieldType("BIGDECIMAL");
else if(metaField.getDataType().indexOf("LOB")>=0||metaField.getDataType().indexOf("MEDIUMTEXT")>=0)
metaField.setFieldType("LONGTEXT");
else if(metaField.getDataType().indexOf("TIME")>=0)
metaField.setFieldType("DATETIME");
else if(metaField.getDataType().indexOf("DATE")>=0) {
metaField.setFieldType("DATE");
}
if(metaField.getFieldType().startsWith("DATE") &&metaField.getDataType().startsWith("TIME") )
{
if(metaField.getFieldName().equalsIgnoreCase("ZHXGSJ")
||metaField.getFieldName().equalsIgnoreCase("ZSJKBGSJ")
||metaField.getFieldName().equalsIgnoreCase("UPDATEDATE") )
{
metaField.setFieldType("DATETIME");
metaField.setPredefined("UPDATEDATE");
}
else if(metaField.getFieldName().equalsIgnoreCase("CJSJ")||metaField.getFieldName().equalsIgnoreCase("CREATEDATE"))
{
metaField.setFieldType("DATETIME");
metaField.setPredefined("CREATEDATE");
}
else if(metaField.getDataPreci()==null||metaField.getDataPreci()==0)
metaField.setFieldType("DATE");
else
metaField.setFieldType("DATETIME");
}
if(metaField.getFieldName().equalsIgnoreCase("ENABLE")||metaField.getFieldName().equalsIgnoreCase("SFSC"))
{
metaField.setPredefined("LOGICVALID");
}
int isKey=0;
Map<String,List<Map>> map = (Map<String, List<Map>>) column.get(j).get("constraints");
if(!ObjectUtils.isEmpty(map)){
metaField.setNullable(map.get("nullable")==null?1:0);
isKey=map.get("primaryKey")==null?0:1;
}else {
metaField.setNullable(1);
}
if(isKey==0&&keyset.contains(metaField.getFieldName()))
isKey=1;
metaField.setKeyField(isKey);
if(isKey==1)
unionKeys.add(metaField);
String name = column.get(j).get("name") == null? "" : column.get(j).get("name").toString();
// 若在父键表查有该数据且属于同一实体则记录一条
for (int l = 0; l < parentEntities.size();l++){
if(name.equals(parentEntities.get(l).keySet().toString().replaceAll("[\\[\\]]", ""))){
if(temp.get("tableName").toString().toUpperCase().equals(parentEntities.get(l).get(name).getRefEntityName())) {
parentEntities.get(l).get(name).setEntityId(metaField.getEntityId());
parentRelationships.add(parentEntities.get(l).get(name));
}
}
}
metaEntityModel.setParentEntitys(parentRelationships);
// 若在子键表查有该数据且属于同一实体则记录一条
for (int l = 0; l < subEntities.size();l++){
if(name.equals(subEntities.get(l).keySet().toString().replaceAll("[\\[\\]]", ""))){
if(temp.get("tableName").toString().toUpperCase().equals(subEntities.get(l).get(name).getRefEntityName())){
subRelationships.add(subEntities.get(l).get(name));
}
}
}
metaEntityModel.setSubEntitys(subRelationships);
metaField.setPhysicalField(1);
metaField.setShowOrder(j+1);
metaField.setEntityName(metaEntityModel.getEntityName());
metaFields.add(metaField);
}
int unionKeysLimit=1;
if(sysModel.getSystemid().equalsIgnoreCase("tyyw2plus")||sysModel.getSystemid().equalsIgnoreCase("tyyw"))
unionKeysLimit=0;
if(unionKeys.size()>unionKeysLimit)
{
MetaField uilid = new MetaField();
unionKeys.get(0).copyTo(uilid,true);
uilid.setFieldName("UILID");
uilid.setFieldLogicName("UILID");
uilid.setCodeName("UILID");
uilid.setKeyField(1);
uilid.setPhysicalField(0);
uilid.setFieldType("TEXT");
uilid.setDataType("VARCHAR");
String expression="";
for(int no=0;no<unionKeys.size();no++)
{
MetaField unikey=unionKeys.get(no);
unikey.setKeyField(0);
unikey.setUnionKey("KEY"+(no+1));
if(!StringUtils.isEmpty(expression))
expression+="||'||'||";
if(unikey.getFieldType().indexOf("DATE")>=0)
expression+=("to_char("+unikey.getFieldName()+" ,'yyyy-MM-dd hh24:mi:ss')");
else if(unikey.getFieldType().indexOf("INT")>=0||unikey.getFieldType().indexOf("DECIMAL")>=0)
expression+=("to_char("+unikey.getFieldName()+")");
else
expression+=unikey.getFieldName();
}
uilid.setExpression(expression);
uilid.setShowOrder(0);
metaFields.add(0,uilid);
}
metaEntityModel.setFields(metaFields);
metaEntityModels.add(metaEntityModel);
sysModel.setEntities(metaEntityModels);
}
return sysModel;
}
private static int[] fieldToLength(String s) {
int[] a={0,0};
if(s.contains("(")) {
String newStr = s.substring(s.indexOf("(") + 1, s.indexOf(")")).replace(" BYTE","").replace(" ","").replace("*","22");
String[] arr=newStr.split(",");
if(arr.length>=1)
a[0]=Integer.parseInt(arr[0]);
if(arr.length>=2)
a[1]=Integer.parseInt(arr[1]);
}
return a;
}
private static String fieldToName(String s) {
if(s.contains("(")){
String newStr = s.substring(0, s.indexOf("("));
return newStr;
}
return s;
}
public static String ConvertXMLtoJSON(String path) {
InputStream is = null;
try {
is = new FileInputStream(path);
String xml;
xml = IOUtils.toString(is);
//将xml转为json
JSONObject xmlJSONObj = XML.toJSONObject(xml);
String jsonPrettyPrintString = xmlJSONObj.toString();
return jsonPrettyPrintString;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@SneakyThrows
protected Liquibase createLiquibase(SpringLiquibase springLiquibase,String changelogPath){
SpringLiquibase.SpringResourceOpener resourceAccessor = springLiquibase.new SpringResourceOpener(changelogPath);
Liquibase liquibase = new Liquibase(changelogPath, resourceAccessor, createDatabase(springLiquibase.getDataSource().getConnection(), resourceAccessor));
liquibase.setIgnoreClasspathPrefix(isIgnoreClasspathPrefix());
if (parameters != null) {
for (Map.Entry<String, String> entry : parameters.entrySet()) {
liquibase.setChangeLogParameter(entry.getKey(), entry.getValue());
}
}
if (isDropFirst()) {
liquibase.dropAll();
}
return liquibase;
}
public boolean isDropFirst() {
return dropFirst;
}
public boolean isIgnoreClasspathPrefix() {
return ignoreClasspathPrefix;
}
protected Database createDatabase(Connection c, ResourceAccessor resourceAccessor) throws DatabaseException {
DatabaseConnection liquibaseConnection;
if (c == null) {
log.info("Null connection returned by liquibase datasource. Using offline unknown database");
liquibaseConnection = new OfflineConnection("offline:unknown", resourceAccessor);
} else {
liquibaseConnection = new JdbcConnection(c);
}
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(liquibaseConnection);
if (StringUtils.trimToNull(this.defaultSchema) != null) {
if (database.supportsSchemas()) {
database.setDefaultSchemaName(this.defaultSchema);
} else if (database.supportsCatalogs()) {
database.setDefaultCatalogName(this.defaultSchema);
}
}
if (StringUtils.trimToNull(this.liquibaseSchema) != null) {
if (database.supportsSchemas()) {
database.setLiquibaseSchemaName(this.liquibaseSchema);
} else if (database.supportsCatalogs()) {
database.setLiquibaseCatalogName(this.liquibaseSchema);
}
}
if (StringUtils.trimToNull(this.liquibaseTablespace) != null && database.supportsTablespaces()) {
database.setLiquibaseTablespaceName(this.liquibaseTablespace);
}
if (StringUtils.trimToNull(this.databaseChangeLogTable) != null) {
database.setDatabaseChangeLogTableName(this.databaseChangeLogTable);
}
if (StringUtils.trimToNull(this.databaseChangeLogLockTable) != null) {
database.setDatabaseChangeLogLockTableName(this.databaseChangeLogLockTable);
}
return database;
}
@SneakyThrows
public String getChangeLog() {
// 自定义属性参数
String uuid = String.valueOf(UUID.randomUUID());
byte[] nameBytes = uuid.getBytes("UTF-8");
String fileid = DigestUtils.md5DigestAsHex(nameBytes);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String fileName = sdf.format(new Date())+".xml";
String fileFullPath = this.liquibasePath+"ibizutil"+ File.separator + fileid+File.separator + fileName;
return fileFullPath;
}
}
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册