您的位置:首页 > 数据库

怎么对比2个数据库的差异

2018-01-25 19:15 225 查看
          今天接到一个任务,测试库和开发库不同步,领导让对比2个库的差异,对比原则表名、字段名、字段属性、字段长度、是否为空,刚接手任务,通过查询USER_TAB_COLUMNS表查询出测试库的表字段属性,之后在开发库新建一个表,把数据导入,之后通过为左右连接为null判断是否存在,一查右4000来条数据,之后要一条一条的比较,这根本就做不了,之后想到了写程序达到效果,思路:

 demo路径:http://download.csdn.net/download/xionglangs/10224457

 1、分别查询到2个库的表名,表子段属性,分别存入MAP中(查询时最好按照表名排序)。

2、第二步,把一个库的表名做为key,表名做value,便利它,如果另外一个map根据key查询不到值,表示此表没有在另外一个库中。

3、之后比较表子段属性,已表名和字段名做key,其余5个属性做值,传入2中查询到的list,过滤key在2中的,就表示2库中都存在表,

但字段维度不同。

4、重复上诉步骤,把比较方位替换。

代码为:

packagecom.sunline.util;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author 熊浪
* @Email xiongl@sunline.cn
* @Time 2018年1月25日 @此类的作用:
*/
public class DatabaseUtil {
private final static Logger logger = LoggerFactory.getLogger(DatabaseUtil.class);

private static final String DRIVER = "oracle.jdbc.OracleDriver";
private static final String URL1 = "jdbc:oracle:thin:@10.22.20.12:1521/UATDEMODB";
private static final String URL2 = "jdbc:oracle:thin:@10.24.0.234:1521/DEVSITDB";
private static final String USERNAME1 = "uat_sungl";
private static final String PASSWORD1 = "uat_sungl";
private static final String USERNAME2 = "sit_sungl";
private static final String PASSWORD2 = "sit_sungl";
private static final String TABLE_INFO = "SELECT DISTINCT TABLE_NAME FROM USER_TABLES";
private static final String TABLE_NAME = "SELECT TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_LENGTH,NULLABLE FROM USER_TAB_COLUMNS";
private static final String SQL = "SELECT * FROM ";// 数据库操作

static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
logger.error("can not load jdbc driver", e);
}
}

/**
* 获取数据库连接
*
* @return
*/
public static Connection getConnection(String url, String userName, String password) {
Connection conn = null;
try {
conn = DriverManager.getConnection(url, userName, password);
} catch (SQLException e) {
logger.error("get connection failure", e);
}
return conn;
}

/**
* 关闭数据库连接
*
* @param conn
*/
public static void closeConnection(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
logger.error("close connection failure", e);
}
}
}

/**
* 获取数据库下的所有表名
*/
public static Map<String, String> getTableInfos(String url, String userName, String password) {
Map<String, String> tableNames = new HashMap<String, String>();
Connection conn = getConnection(url, userName, password);
PreparedStatement pst = null;
ResultSet rs = null;
try {
pst = conn.prepareStatement(TABLE_NAME);
rs = pst.executeQuery();
while (rs.next()) {
tableNames.put(rs.getString(1) + "=" + rs.getString(2), rs.getString(1) + "=" + rs.getString(2) + "=" + rs.getString(3) + "=" + rs.getString(4) + "=" + rs.getString(5) + "=" + rs.getString(1));
}
} catch (SQLException e) {
logger.error("getTableNames failure", e);
} finally {
try {
rs.close();
closeConnection(conn);
} catch (SQLException e) {
logger.error("close ResultSet failure", e);
}
}
return tableNames;
}

public static Map<String, String> getTableNames(String url, String userName, String password) {
Map<String, String> tableNames = new HashMap<String, String>();
Connection conn = getConnection(url, userName, password);
PreparedStatement pst = null;
ResultSet rs = null;
try {
pst = conn.prepareStatement(TABLE_INFO);
rs = pst.executeQuery();
while (rs.next()) {
tableNames.put(rs.getString(1), rs.getString(1));
}
} catch (SQLException e) {
logger.error("getTableNames failure", e);
} finally {
try {
rs.close();
closeConnection(conn);
} catch (SQLException e) {
logger.error("close ResultSet failure", e);
}
}
return tableNames;
}

/**
* 获取表中所有字段名称
*
* @param tableName 表名
* @return
*/
public static List<String> getColumnNames(String tableName, String url, String userName, String password) {
List<String> columnNames = new ArrayList<>();
// 与数据库的连接
Connection conn = getConnection(url, userName, password);
PreparedStatement pStemt = null;
String tableSql = SQL + tableName;
try {
pStemt = conn.prepareStatement(tableSql);
// 结果集元数据
ResultSetMetaData rsmd = pStemt.getMetaData();
// 表列数
int size = rsmd.getColumnCount();
for (int i = 0; i < size; i++) {
columnNames.add(rsmd.getColumnName(i + 1));
}
} catch (SQLException e) {
logger.error("getColumnNames failure", e);
} finally {
if (pStemt != null) {
try {
pStemt.close();
closeConnection(conn);
} catch (SQLException e) {
logger.error("getColumnNames close pstem and connection failure", e);
}
}
}
return columnNames;
}

/**
* 获取表中所有字段类型
*
* @param tableName
* @return
*/
public static List<String> getColumnTypes(String tableName, String url, String userName, String password) {
List<String> columnTypes = new ArrayList<>();
// 与数据库的连接
Connection conn = getConnection(url, userName, password);
PreparedStatement pStemt = null;
String tableSql = SQL + tableName;
try {
pStemt = conn.prepareStatement(tableSql);
// 结果集元数据
ResultSetMetaData rsmd = pStemt.getMetaData();
// 表列数
int size = rsmd.getColumnCount();
for (int i = 0; i < size; i++) {
columnTypes.add(rsmd.getColumnTypeName(i + 1));
}
Arrays.sort(columnTypes.toArray());
} catch (SQLException e) {
logger.error("getColumnTypes failure", e);
} finally {
if (pStemt != null) {
try {
pStemt.close();
closeConnection(conn);
} catch (SQLException e) {
logger.error("getColumnTypes close pstem and connection failure", e);
}
}
}
return columnTypes;
}

public static List<List<String>> selectTableInfo(Map<String, String> uat, Map<String, String> sit) {
Set<Entry<String, String>> uats = uat.entrySet();
Iterator<Entry<String, String>> it = uats.iterator();
Entry<String, String> infos = null;
String uatInfo = "", sitInfo = "";
List<List<String>> list = new ArrayList<List<String>>();
String[] uatArray = null, sitArray = null;
while (it.hasNext()) {
infos = it.next();
uatInfo = infos.getValue();
sitInfo = sit.get(infos.getKey());
if (!uatInfo.equals(sitInfo)) {
List<String> isDiffent = new ArrayList<String>();
uatArray = uatInfo.split("=");
for (int i = 0; i < uatArray.length; i++) {
isDiffent.add(uatArray[i]);
}
if (sitInfo != null) {
sitArray = sitInfo.split("=");
for (int i = 0; i < sitArray.length; i++) {
isDiffent.add(sitArray[i]);
}
} else {
for (int i = 0; i < uatArray.length; i++) {
isDiffent.add("");
}
}
list.add(isDiffent);
}
}
return list;
}

public static List<List<String>>selectTableInfo(Map<String, String> uat, Map<String, String> sit, String prefix) {
Set<Entry<String, String>> uats = uat.entrySet();
Iterator<Entry<String, String>> it = uats.iterator();
Entry<String, String> infos = null;
String uatInfo = "", sitInfo = "";
List<List<String>> list = new ArrayList<List<String>>();
String[] uatArray = null, sitArray = null;
int len=0;
while (it.hasNext()) {
infos = it.next();
uatInfo = infos.getValue();
sitInfo = sit.get(infos.getKey());
if (!uatInfo.equals(sitInfo)) {
uatArray = uatInfo.split("=");
if (prefix != null && prefix.contains(uatArray[uatArray.length - 1])) {
continue;
}
List<String> isDiffent = new ArrayList<String>();
if(prefix!=null)
len=uatArray.length-1;
else
len=uatArray.length;
for (int i = 0; i < len; i++) {
isDiffent.add(uatArray[i]);
}
if (sitInfo != null) {
sitArray = sitInfo.split("=");
for (int i = 0; i < len; i++) {
isDiffent.add(sitArray[i]);
}
} else {
for (int i = 0; i < len; i++) {
isDiffent.add("");
}
}
list.add(isDiffent);
}
}
return list;
}

public static void main(String[] args) {
Map<String, String> uatTable = getTableNames(URL1, USERNAME1, PASSWORD1);
Map<String, String> sitTable = getTableNames(URL2, USERNAME2, PASSWORD2);
Map<String, String> uatInfos = getTableInfos(URL1, USERNAME1, PASSWORD1);
Map<String, String> sitInfos = getTableInfos(URL2, USERNAME2, PASSWORD2);
String[] title = {"表名", "字段名", "字段类型", "字段长度", "是否为空", "表名", "字段名", "字段类型", "字段长度", "是否为空"};
String[] infos = {"表名", "字段名", "字段类型", "字段长度", "是否为空", "表名", "字段名", "字段类型", "字段长度", "是否为空"};
List<List<String>> uatTables = selectTableInfo(uatTable, sitTable, null);
List<List<String>> infoTables = selectTableInfo(sitTable, uatTable, null);
StringBuffer sbOne = new StringBuffer();
StringBuffer sbTwo = new StringBuffer();
for (List<String> list:uatTables)
sbOne.append(list.get(0)+",");
for (List<String> list:infoTables)
sbTwo.append(list.get(0)+",");
ExcelManage.writeInfoToExcel("UAT与SIT表名比较,前面现实UAT", "D:" + File.separator + "长亮", "UAT-SIT_TABLE", "xls", title, uatTables, TableInfoBean.class);
ExcelManage.writeInfoToExcel("UAT与UAT字段名比较,前面现实UAT", "D:" + File.separator + "长亮", "UAT-SIT_CLOUMN", "xls", infos, selectTableInfo(uatInfos, sitInfos, sbOne.toString()), SujuInfoBean.class);
ExcelManage.writeInfoToExcel("SIT与UAT表名比较,前面现实SIT", "D:" + File.separator + "长亮", "SIT-UAT_TABLE", "xls", title, infoTables, TableInfoBean.class);
ExcelManage.writeInfoToExcel("SIT与UAT字段名比较,前面现实SIT", "D:" + File.separator + "长亮", "SIT-UAT_CLOUMN", "xls", infos, selectTableInfo(sitInfos, uatInfos, sbTwo.toString()), SujuInfoBean.class);
}
}

package com.sunline.util;

/**
* @author 熊浪
* @Email xiongl@sunline.cn
* @Time 2018/1/25
* @此类的作用:
*/
public class TableInfoBean {
private String tableName;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
}

package com.sunline.util;

/**
* @author 熊浪
* @Email xiongl@sunline.cn
* @Time 2018年1月25日
* @此类的作用:
*/
public class SujuInfoBean {
private String tableNameOne;
private String cloumnOne;
private String typeOne;
private String cloumnLengthOne;
private String isOrNullOne;
private String tableNameTwo;
private String cloumnTwo;
private String typeTwo;
private String cloumnLengthTwo;
private String isOrNullTwo;

public String getTableNameOne() {
return tableNameOne;
}

public void setTableNameOne(String tableNameOne) {
this.tableNameOne = tableNameOne;
}

public String getCloumnOne() {
return cloumnOne;
}

public void setCloumnOne(String cloumnOne) {
this.cloumnOne = cloumnOne;
}

public String getTypeOne() {
return typeOne;
}

public void setTypeOne(String typeOne) {
this.typeOne = typeOne;
}

public String getCloumnLengthOne() {
return cloumnLengthOne;
}

public void setCloumnLengthOne(String cloumnLengthOne) {
this.cloumnLengthOne = cloumnLengthOne;
}

public String getIsOrNullOne() {
return isOrNullOne;
}

public void setIsOrNullOne(String isOrNullOne) {
this.isOrNullOne = isOrNullOne;
}

public String getTableNameTwo() {
return tableNameTwo;
}

public void setTableNameTwo(String tableNameTwo) {
this.tableNameTwo = tableNameTwo;
}

public String getCloumnTwo() {
return cloumnTwo;
}

public void setCloumnTwo(String cloumnTwo) {
this.cloumnTwo = cloumnTwo;
}

public String getTypeTwo() {
return typeTwo;
}

public void setTypeTwo(String typeTwo) {
this.typeTwo = typeTwo;
}

public String getCloumnLengthTwo() {
return cloumnLengthTwo;
}

public void setCloumnLengthTwo(String cloumnLengthTwo) {
this.cloumnLengthTwo = cloumnLengthTwo;
}

public String getIsOrNullTwo() {
return isOrNullTwo;
}

public void setIsOrNullTwo(String isOrNullTwo) {
this.isOrNullTwo = isOrNullTwo;
}

}

package com.sunline.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* @author 熊浪
* @Email xiongl@sunline.cn
* @Time 2018年1月25日 @此类的作用:
*/
public class ExcelManage {
public static boolean writeInfoToExcel(String fileTitle, String path, String fileName, String fileType, String[] title, List<List<String>> list, Class<?> clazz) {
boolean flag = false;
try {
writer(fileTitle, path, fileName, fileType, insertInfoToBean(list, clazz), title);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}

private static List<Object> insertInfoToBean(List<List<String>> list, Class<?> clazz) throws Exception {
List<Object> objs = new ArrayList<Object>();
boolean flag = false;
Field[] fields = clazz.getDeclaredFields();
for (int i = 0, len = list.size(); i < len; i++) {
Object obj = clazz.newInstance();
for (int j = 0; j < fields.length; j++) {
flag = fields[j].isAccessible();
fields[j].setAccessible(true);
try {
fields[j].set(obj, list.get(i).get(j));
fields[j].setAccessible(flag);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
objs.add(obj);
}
return objs;
}

private static void writer(String fileTitle, String path, String fileName, String fileType, List<Object> list, String titleRow[]) throws Exception {
Workbook wb = null;
String excelPath = path + File.separator + fileName + "." + fileType;
File file = new File(excelPath);
Sheet sheet = null;
// 创建工作文档对象
if (!file.exists()) {
if (fileType.equals("xls")) {
wb = new HSSFWorkbook();
} else if (fileType.equals("xlsx")) {
wb = new XSSFWorkbook();
} else {
throw new Exception("文件格式不正确");
}
// 创建sheet对象
sheet = (Sheet) wb.createSheet("sheet1");
OutputStream outputStream = new FileOutputStream(excelPath);
wb.write(outputStream);
outputStream.flush();
outputStream.close();
} else {
if (fileType.equals("xls")) {
wb = new HSSFWorkbook();
} else if (fileType.equals("xlsx")) {
wb = new XSSFWorkbook();
} else {
throw new Exception("文件格式不正确");
}
}
// 创建sheet对象
if (sheet == null) {
sheet = (Sheet) wb.createSheet("sheet1");
}
// 添加表头
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
row.setHeight((short) 540);
cell.setCellValue(fileTitle); // 创建第一行
CellStyle style = wb.createCellStyle(); // 样式对象
// 设置单元格的背景颜色为淡蓝色
style.setFillForegroundColor(HSSFColor.PALE_BLUE.index);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);// 垂直
style.setAlignment(CellStyle.ALIGN_CENTER);// 水平
style.setWrapText(true);// 指定当单元格内容显示不下时自动换行
cell.setCellStyle(style); // 样式,居中
Font font = wb.createFont();
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
font.setFontName("宋体");
font.setFontHeight((short) 280);
style.setFont(font);
// 单元格合并
// 四个参数分别是:起始行,起始列,结束行,结束列
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 7));
sheet.autoSizeColumn(5200);
row = sheet.createRow(1); // 创建第二行
for (int i = 0; i < titleRow.length; i++) {
cell = row.createCell(i);
cell.setCellValue(titleRow[i]);
cell.setCellStyle(style); // 样式,居中
sheet.setColumnWidth(i, 20 * 256);
}
row.setHeight((short) 540);
Field[] fields = null;
if (!list.isEmpty())
fields = list.get(0).getClass().getDeclaredFields();
// 循环写入行数据
boolean flag = false;
for (int i = 0; i < list.size(); i++) {
row = (Row) sheet.createRow(i + 2);
row.setHeight((short) 500);
for (int j = 0; j < fields.length; j++) {
flag = fields[j].isAccessible();
fields[j].setAccessible(true);
try {
row.createCell(j).setCellValue("" + fields[j].get(list.get(i)));
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new Exception(e.getMessage());
}
fields[j].setAccessible(flag);
}
}
// 创建文件流
OutputStream stream = new FileOutputStream(excelPath);
// 写入数据
wb.write(stream);
// 关闭文件流
stream.close();
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: