java根据xml中插入语句生成创建表字段
java根据xml中插⼊语句⽣成创建表字段
postgresql数据库使⽤遇到的问题及解决⽅案
该⽂章主要内容
1.⽬前从⼯程的xml中⽣成sql是从sqlmapper的resultMap⽣成创建表语句
该⽅案有明显的局限性质,
1.查询语句不是标准的带有resultMap的语句,会忽略该表⽣成
2.同⼀样⼀个表查询有多种变种形式,那对应就会有多种resultMap,处理只相差⼏个字段的resultMap其实⽣成的字段可能还不⼀样
2.该⽅案的实现⽅式
1.根据插⼊语句⽣成创建表语句,因为⼀个⼯程中插⼊数据的地⽅基本在⼀个⽂件,⽽且插⼊基本就是⼀条语句就解决,没有复杂的嵌套循环插⼊
2.能准确区别该模块⽣产数据表和依赖基础数据表
有插⼊语句代表这个表是这个模块⽣产的数据,那这个表就⼀定需要创建,在⼀个模块中肯定存在没有插⼊语句但是⼜存在查询表语句的表,那这⼀类表就统⼀归为该模块依赖的基础数据表,
为什么需要这么明确的区分,因为依赖的基础数据表是需要我们在运⾏之前导⼊基础数据的,⽽造基础数据是涉及到该模块是否能运⾏起来的关键
3.该⽅案的实现模块细节⽅法解释
1.main⽅法
指定⽣成创建sql的⽂件夹位置以及⽂件名
指定sqlMapper在代码⼯程中的位置
2.buildInsertSql2Table
⽣成建表sql⽂件⽅法,打印出现超过>=2的表的表名字以及汇总等analysis执⾏完成之后再⽣成创建表sql
3.analysis
根据指定的⽬录进⾏遍历分析,直到是xml⽂件才执⾏analysisSql⽅法
4.analysisSql
获取xml中的sql⽂件,有写⾃增索引的特殊处理,获取命名空间(nameSpace)
分析单个的sqlmap配置⽂件
只处理insert⽅法
根据mapper的命名空间和调⽤⽅法获取插⼊sql的⼊参class  getMethodParamClass
⽣成插⼊sql语句 createTable创建表中包括
替换dateformat⽇期类型为默认字段createTime
数据库表字段需要将\n,(,)替换为逗号
vo字段列需要将空格,#{,}都替换为空,使⽤,分割
没有id主键的⾃动补齐主键
统计对同⼀表有重复创建表的sql,需要⽤户⼿动合并两个表
创建表头语句,包括drop语句,create语句,以及表尾部括号
创建表列语句 createCloumns
根据表字段和vo映射字段⽣成表列字段
根据vo字段动态构建jdbcType
如果为id主键,增加⾃增定义
有重复的插⼊语句使⽤map去重
返回特定占位符,⽅便替换
有重复出现的表,则需要在map中做列字段汇总
将⽣成的sql写⼊⽂件 writeSql2File
4.⽂件执⾏调⽤⽅式
1.先指定main⽅法中的sql⽣成位置,以及sqlMapper的位置
2.先执⾏⼀次⽅法,会在控制台打印出有哪些表重复[出现两条创建表语句的表名为],把这些表复制放⼊
String[] tableAppearFrequency中
3.再次执⾏main⽅法,因为tableAppearFrequency有重复的插⼊表明,所以会对重复的插⼊语句有不同的;列进⾏⾃动汇总
4.执⾏完成之后打开sql⽬录即可查看创建的创建表语句了
5.除了这些之外的查询表怎么获取 使⽤EmEditor直接搜索from和join关键字,然后进⾏各种变化操作获取到所有的查询的表明,之后⽤for循环进⾏去重即可获得基础表数据是哪些表
package com.sqlmap2Table;
import com.alibaba.fastjson.JSON;
import llections4.MapUtils;
import org.apachemons.lang3.StringUtils;
import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
import java.io.*;
import flect.Field;
import flect.Method;
import flect.Type;
import java.util.*;
import urrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
/**
* @description 根据xml的insert语句⽣成表创建语句
* @author pengXiong
* @date 2020/8/5 19:19
*/
public class Sqlmap2Table {
public static Sqlmap2Table instance =new Sqlmap2Table();
// 默认所有的varchar都是512,可以保证满⾜绝⼤多数的字段
private final String DEFAULT_VARCHAR_LENGTH ="varchar(256)";
// 有多条插⼊语句⽣成的create表做占位使⽤,⽅便替换
private final String COLUMN_PLACEHOLDER ="%Cloumns%";
private final String SELF_INCRECE_PRIMARY_KEY ="id";
private final String SELF_INCRECE_PRIMARY_VALUE =" primary key auto_increment";
// 统计对同⼀表有重复创建表的sql,需要⽤户⼿动合并两个表
private Map<String, Integer> tableAppearFrequency =new HashMap<>();
private Map<String, Map<String, String>> combinaTableAppearFrequency =new HashMap<>();
private Sqlmap2Table(){
// 放置重复出现的需要组合的表和表字段,最后完成后统⼀写⽂件, 该重复表key值运⾏⼀次后请从打印⽇志[出现两条创建表语句的表名为 : ]中取到
String[] tableAppearFrequency =new String[]{
// 出现两条创建表语句的表名放⼊这⾥
""
};
for(String str : tableAppearFrequency){
combinaTableAppearFrequency.put(str,new HashMap<>());
}
}
public static void main(String[] args)throws JDOMException, IOException {
String sqlFile ="I:/IT/创建表/create_table.sql";
String sqlMapPath ="I:/IT/server/src/main/resources/mybatis/mapper";//这⾥指定你的sqlmap配置⽂件所在路径
// 统计对同⼀表有重复创建表的sql,需要⽤户⼿动合并两个表
// 统计对同⼀表有重复创建表的sql,需要⽤户⼿动合并两个表
Sqlmap2Table.instance.buildInsertSql2Table(sqlMapPath, sqlFile);
}
/**
* 打印出现超过>=2的表的表名字以及汇总等analysis执⾏完成之后再⽣成创建表sql
* @param sqlMapPath
* @param sqlFilePath
* @throws IOException
* @throws JDOMException
*/
public void buildInsertSql2Table(String sqlMapPath, String sqlFilePath)throws IOException, JDOMException {
// 先将⽂件删除
File sqlFile =new File(sqlFilePath);
sqlFile.delete();
// ⽣成建表sql⽂件⽅法
analysis(sqlMapPath,sqlFilePath);
// 打印出现超过>=2的表的表名字
List<Map.Entry> result = Set().stream().filter(table -> Value()>=2).List());        System.out.println("出现两条创建表语句的表名和出现数量为 : "+ JSONString(result));好听好看的游戏名字
System.out.println("出现两条创建表语句的表名为 : "+ JSONString(result.stream().map(tabl -> Key()).toArray()));
// 对重复出现表的表字段在map中汇总等analysis执⾏完成之后再⽣成创建表sql
if(MapUtils.isNotEmpty(combinaTableAppearFrequency)){
for(Map.Entry<String, Map<String, String>> entry : Set()){
Map<String, String> colunmMap = Value();
String sql = (COLUMN_PLACEHOLDER);
StringBuffer sbCloumns =new StringBuffer();
for(Map.Entry<String, String> coluns : Set()){
String key = Key();
String value = Value();
if(Objects.equals(key, COLUMN_PLACEHOLDER)){
continue;
}
// 构建表列参数
sbCloumns =buildCloumns(sbCloumns, key, value);
}
sql = place(COLUMN_PLACEHOLDER, String());
// 将⽣成的sql写⼊⽂件
writeSql2File(sql, sqlFilePath);
}
}
}
/**
* 根据指定的⽬录进⾏遍历分析
*
* @param path
* @throws IOException
* @throws JDOMException
*/
private void analysis(String path, String sqlFile)throws IOException, JDOMException {
File filePath =new File(path);
if(filePath.isDirectory()&&!Name().equals(".svn")){
File[] fileList = filePath.listFiles();
for(File file : fileList){
if(file.isDirectory()){
AbsolutePath(),sqlFile);
}else{
AbsolutePath(),sqlFile);
}
}
}
}
/**
* 分析单个的sqlmap配置⽂件
* 分析单个的sqlmap配置⽂件
*
* @param sqlMapFile
* @throws IOException
* @throws JDOMException
*/
带明的成语
private void analysisSql(String sqlMapFile, String sqlFilePath)throws IOException, JDOMException {
// System.out.println("************"+sqlMapFile);
boolean isNull=false;
/**
* 这⾥要把sqlmap⽂件中的这⼀⾏去掉:<br>
* <!DOCTYPE sqlMap PUBLIC "-//iBATIS//DTD SQL Map 2.0//EN" "www.ibatis/dtd/sql-map-2.dtd"><br>        * 否则JDom根据⽂件创建Document对象时,会报不到www.ibatis这个异常,导致渲染不成功。
*/
String xmlString =filterRead(sqlMapFile,"<!DOCTYPE");
Document doc =getDocument(xmlString);
Element foo = RootElement();
// sql统⼀转换为⼩写,并且替换sql中的关键字字符
String sqlStr =generateKeyWords(foo);
// 获取拆分出的sql
List<String> sqls = Arrays.asList(sqlStr.split(";")).parallelStream().filter( sql ->{
return// sql不为空
StringUtils.isNotBlank(sql)
// 不包含last_insert_id,last_insert_id会被拆成两个放⼊list中
&&!ains("last_insert_id()");
//&& !ains("LAST_INSERT_ID()");
}).List());
// 获取命名空间
String mapper =((Attributes().get(0)).getValue();
// 获取sql中Element的具体信息
List<Element> allChildren = Children();
for(int i=0; i<allChildren.size(); i++){
Element element = (i);
// 获取当中的某⼀条sql
String operatorType = Name();
if(!"insert".equals(operatorType)){
// 只按照insert⽅法处理
continue;
}
// 获取执⾏的sql
String sql = (i);
if(!ains("insert")|| ains("@")){
// 特殊场景处理,百度云 搜索
// 1.有的sql包含查询语句,将该数据剔除
// 2.存储过程暂时先不⽣成sql
System.out.println("这是⼀条存储过程sql : "+sql);
continue;
}
/
/ 根据mapper和调⽤⽅法获取插⼊sql的⼊参class
Class[] paramClass =getMethodParamClass(mapper, element);
System.out.println("contentSql : "+sql);
// ⽣成插⼊sql语句
String createTableSql =createTable(sql, paramClass);
System.out.println("createTableSql : "+createTableSql);
防震减灾手抄报内容
// 将⽣成的sql写⼊⽂件
writeSql2File(createTableSql, sqlFilePath);
}
}
/**
* sql统⼀转换为⼩写,并且替换sql中的关键字字符
* @param foo 单个sql元素
* @return 替换后的sql
*/
private String generateKeyWords(Element foo){
String sqlStr = Value().toLowerCase();
String sqlStr = Value().toLowerCase();
sqlStr = sqlStr
.replace("\n","")
.replace("insert ",";insert ")
.replace("update ",";update ")
.
replace("delete ",";delete ")
.replace("select ",";select ");
return sqlStr;
}
/**
* 根据mapper和调⽤⽅法获取插⼊sql的⼊参class
* @param mapper dao层映射
* @param element 单个插⼊sql元素
* @return
*/
private Class[]getMethodParamClass(String mapper, Element element){
List<Attribute> elementAttrs = Attributes();
// 获取sql配置⽅法的名称,可以字段为id
String methodName = null;
for(Attribute att : elementAttrs){
if("id".Name())){
methodName = Value();
break;寂静岭起源攻略
}
}
Class<?> mapperClass  = null;
try{
mapperClass = Class.forName(mapper);
}catch(ClassNotFoundException e){
System.out.println("ClassNotFoundException Message : "+e.getMessage()+"mapperClass :"+JSONString(mapperClass));
e.printStackTrace();
}
Method[] methods = Methods();
for(Method method : methods){
if(methodName.Name())){
// 判定是不是有泛型参数
boolean havaGenericparam =
Arrays.GenericParameterTypes()).stream().allMatch( param -> TypeName().contains("<"));
if(!havaGenericparam){
// 不是泛型直接返回参数类型
ParameterTypes();
}else{
// 泛型参数需要获取泛型类型<>尖括号中的真正数据类型
Type[] types = GenericParameterTypes();
Class[] clazz =new Class[types.length];
for(int i=0; i<types.length; i++){
String paramClazz = types[i].getTypeName();
ains("Map")){
// Map<String, String>泛型截取最后⼀个String
paramClazz =(paramClazz = types[i].getTypeName()).substring(paramClazz.lastIndexOf(", ")+1, paramClazz.indexOf(">"));
}else ains("<")){
// List<String>泛型截取最后⼀个String
paramClazz =(paramClazz = types[i].getTypeName()).substring(paramClazz.lastIndexOf("<")+1, paramClazz.indexOf(">"));
}
try{
// 获取到泛型中真正的参数后实例化为class
公务员转正个人总结clazz[i]= Class.im());
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
return clazz;
}
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。