SQL优化及多数据库支持分享(二)

444 阅读2分钟

「这是我参与11月更文挑战的第 10 天,活动详情查看:2021最后一次更文挑战

1、前言

​ 上一次,我们说到了DB2环境的搭建,本次我们来分享下,如何把oracle中的表结构及数据同步到db2与mariadb中。 ​ 刚开始,我拿到这个需求后也是很懵,有点无从下手。项目小组长给了我一个介绍db2与oracle有哪些不同的博客,然后就让我自己搞了了。整个项目有300多张表,挨个手工替换建表语句肯定是不现实的。后面通过百度也了解到了,阿里开源的datax等框架,但是datax并不支持oracle到db2的迁移。后来还是通过google,找到了一款SQL语句转换工具,SQLines (这个是线上版的,同时也有安装包) 现在我们就可以通过java程序批量将表结构转换成db2下的SQL,然后再写一个小工具先查出来,再插入到db2中即可。(这里也去找了些开源项目,但大多都好久没有维护了,调试运行起来太麻烦,干脆就自己简单写了下)

2、同步表结构及数据

​ 在这里我是先,把所有的表结构SQL语句导出到本地,然后批量转换成对应的DB2的建表语句。同步数据这里,因为就是要求简单快速,就也没有使用mybatis这些,我是简单写了一个小工具,这里推荐大家使用下hutool的数据库操作工具类,使用起来很简单。

@Slf4j
public class ConvertSQLXML {
	
	public static void main(String[] args) {
		String pathPub = "D:\\data";
		log.debug("加载SQL-INFO配置:" + pathPub);
		List<String> paths = new ArrayList<String>();
		getDependencyPath(paths, pathPub, (f, n) -> {
			return n.endsWith("info.xml");
		});
		log.info("SQL:{}", paths);
		paths.forEach(v -> {
			try {
				write(v);
			} catch (IOException e) {
				e.printStackTrace();
			}
		});
		
	}
	
	private static void write(String filePath) throws IOException {
		//1、一行一行的读
		File file = new File(filePath);
		String outSrc = "C:\\data";
		String outFileOraclePath = outSrc + File.separator + "oracle-" + file.getName();
		String outFileMySQLPath = outSrc + File.separator + "mysql-" + file.getName();
		String outFileDB2Path = outSrc + File.separator + "db2-" + file.getName();
		File outFile = new File(outFileOraclePath);
		File outFileMySQL = new File(outFileMySQLPath);
		File outFileDB2 = new File(outFileDB2Path);
		if (!outFile.exists()) {
			outFile.createNewFile();//有路径才能创建文件
		}
		outFileMySQL.createNewFile();//有路径才能创建文件
		outFileDB2.createNewFile();//有路径才能创建文件
	    BufferedReader reader = null;
	    BufferedWriter writer = null;
	    try {
	    	writer = new BufferedWriter(new FileWriter(outFile, true));
	        reader = new BufferedReader(new FileReader(file));
	        String tempStr;
	        while ((tempStr = reader.readLine()) != null) {
	        	if (StringUtils.isBlank(tempStr) || Pattern.matches(xml, tempStr) || Pattern.matches(DOCTYPE, tempStr)) {
					continue;
				}
	        	if (Pattern.matches(sqlinfo, tempStr) || Pattern.matches(check, tempStr) 
	        			|| Pattern.matches(CDATA, tempStr) || Pattern.matches(sql, tempStr)
	        			|| Pattern.matches(sp, tempStr)) {
	        		writer.newLine();
					continue;
				}
	        	writer.write(tempStr);
	        	writer.newLine();
	        }
	        reader.close();
	        writer.flush();
	        writer.close();
	        convertOracleToOther(outFileOraclePath, outFileMySQLPath, "mysql");
	        convertOracleToOther(outFileOraclePath, outFileDB2Path, "db2");
	    } catch (IOException e) {
	        e.printStackTrace();
	    } finally {
            reader.close();
	        writer.close();
	    }
	}
	
	private static void convertOracleToOther(String filePathSrc, String filePathOut, String targetType) {
		//sqlines.exe -s=oracle -t=sql -in=script.sql
		String cmd = "C:\\sqlines.exe";
        try {
        	//执行exe  cmd可以为字符串(exe存放路径)也可为数组,调用exe时需要传入参数时,可以传数组调用(参数有顺序要求)
        	new ProcessBuilder(cmd," -s=oracle"," -t=" + targetType, " -in=" + filePathSrc, " -out=" + filePathOut).start();
        } catch (Exception e) {
            e.printStackTrace();
        }
	}
	
	private static void getDependencyPath(List<String> paths, String path, FilenameFilter filter){
		File file =new File(path);
		File[] files = file.listFiles();
		String[] names = file.list();
		if(names != null){
			for(int i=0;i < names.length;i++){
				if (filter.accept(null , names[i])) {
					paths.add(path + File.separator + names[i]);
				}
			}
		}
		for (File a : files) {
			if(a.isDirectory()){ 				//判断有子文件
				getDependencyPath(paths, a.getAbsolutePath()+"\\", (f, n) -> {
					return n.endsWith("info.xml");
				});
			}
		}
	}
	
}