Java对比两个数据库中的表和字段,写个冷门的东西

简介: Java对比两个数据库中的表和字段,写个冷门的东西 转载的 来源网络   目前所在的项目组距离下个版本上线已经很近了,就面临了一个问题:开发人员在开发库上根据需要增加数据表、数据字段、或者变更了字段类型或者字段长度等等。

Java对比两个数据库中的表和字段,写个冷门的东西

转载的 来源网络

 

目前所在的项目组距离下个版本上线已经很近了,就面临了一个问题:开发人员在开发库上根据需要增加数据表数据字段、或者变更了字段类型或者字段长度等等。

由于时间比较紧迫,导致在开发过程中不可能一一把DDL数据库脚本记录下来,在比较大的项目中,比如我所在项目开发的系统大概包含了800张左右的表,字段上10000个的情况下,人工处理明显不可行,所以我们就得通过程序来判断比对,哪些是我们需要新增加的表,哪些是我们需要新增加的字段,哪些是我们需要修改的字段。

因为我开发的项目是为银行工作的,所以数据量无疑很大,所以这个Java类可以用于几乎大多数情况了,当前情况是正在运行的生产服务器上有个数据库-->生产库,我们开发人员服务器上有个数据库-->开发库,就需要我们将两库差异对比出来,我差不多花了1个小时写了下面几个类,运行一下就可以将差异化的地方写入文件中,便于后续写DDL脚本处理。

首先是一个 Table 类,代表了我们数据库中的一张表,其中存在String类型的表名、和存放若干个各种字段的HashMap()

 
 
 
 
Java
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package test;
import java.util. HashMap;
public class Table {
public String tableName;
public HashMap columns = new HashMap();
 
public Table(String tableName) {
this.tableName = tableName;
}
 
public String getTableName() {
return tableName;
}
 
public void setTableName(String tableName) {
this.tableName = tableName;
}
 
public HashMap getColumns() {
return columns;
}
 
public void setColumns(HashMap columns) {
this.columns = columns;
}
}

接着就是一个 Column 类,代表了数据库中的一个字段,其中属性就是字段名、字段类型、字段长度,当然可以根据自己的需求加入更多要素

 
 
 
 
Java
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package test;
public class Column {
public String columnName;
public String dataType;
public int length;
 
public Column(String columnName, String dataType, int length) {
this.columnName = columnName;
this.dataType = dataType;
this.length = length;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
}

其实这个方法完全可以不用上面两个类的,但是为了写起来理解方便,所以就用了,执行效率其实还不错,几百张表几秒钟就跑完了

下面是实现这个需求的主要类,写出来的主要目的就是希望能帮我改进一下,毕竟自己写程序没有太多的设计理念和大局观,希望能者修改修改:

 
 
 
 
Java
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
package test;
package test;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
 
import com.amarsoft.are.sql.ASResultSet;
import com.amarsoft.are.sql.Transaction;
import com.amarsoft.are.util.DataConvert;
 
public class CompareTable {
 
public static StringBuffer[] sb = { new StringBuffer(), new StringBuffer(),
new StringBuffer(), new StringBuffer(), new StringBuffer(),
new StringBuffer() };
 
public static Transaction getTransaction_product() throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.1.1:1621:orcl", "demo1", "demo1");
if (conn != null)System.out.println("数据库加载成功!");
Transaction transaction = new Transaction(conn);
return transaction;
}
 
public static Transaction getTransaction_develop() throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.1.2:1621:orcl", "demo2", "demo2");
if (conn != null)System.out.println("数据库加载成功!");
Transaction transaction = new Transaction(conn);
return transaction;
}
 
public static void main(String[] args) throws Exception {
compareTables(); // 比较数据库
writeFile(); // 写入文件
}
 
 
 
public static void compareTables() throws Exception {
 
// 生产数据库连接
Transaction trans_product = getTransaction_product();
Map<</SPAN>String, Table> map_product = getTables(trans_product);
 
// 开发数据库连接
Transaction trans_develop = getTransaction_develop();
Map<</SPAN>String, Table> map_develop = getTables(trans_develop);
 
// 遍历开发库Map
for (Iterator iter_table = map_develop.keySet().iterator(); iter_table
.hasNext();) {
String key_table = (String) iter_table.next();
Table table_develop = map_develop.get(key_table);// 获得开发库中的表
Table table_product = map_product.get(key_table);// 尝试从生产库中获得同名表
if (table_product == null) { // 如果获得表为空,说明开发存在,生产不存在
append(table_develop, null, 2);
} else { // 表相同,判断字段、字段类型、字段长度
for (Iterator iter_column = table_develop.columns
.keySet().iterator(); iter_column.hasNext();) {
String key_column = (String) iter_column.next();
Column column_develop = table_develop.columns.get(key_column);// 获得开发库中的列
Column column_product = table_product.columns.get(key_column);// 尝试从生产库中获得同名列
if (column_product == null) {// 如果列名为空,说明开发存在,生产不存在
append(table_develop, column_develop, 4);
} else {// 说明两者都存在
if (!column_develop.dataType.equals(column_product.dataType))// 字段类型不一致
append(table_develop, column_develop, 5);
if (column_develop.length != column_product.length)// 字段长度不一致
append(table_develop, column_develop, 6);
}
}
}
}
 
// 遍历生产库Map
for (Iterator iter_table = map_product.keySet().iterator(); iter_table
.hasNext();) {
String key_table = (String) iter_table.next();
Table table_product = map_product.get(key_table);// 尝试从生产库中获得同名表
Table table_develop = map_develop.get(key_table);// 获得开发库中的表
if (table_develop == null) { // 如果获得表为空,说明开发存在,生产不存在
append(table_product, null, 1);
} else { // 表相同,判断字段、字段类型、字段长度
for (Iterator iter_column = table_product.columns
.keySet().iterator(); iter_column.hasNext();) {
String key_column = (String) iter_column.next();
Column column_product = table_product.columns.get(key_column);// 获得生产库中的列
Column column_develop = table_develop.columns.get(key_column);// 尝试从开发库中获得同名列
if (column_develop == null) {// 如果列名为空,说明生产存在,开发不存在
append(table_product, column_product, 3);
}
}
}
}
}
 
 
public static Map<</SPAN>String, Table> getTables(Transaction transaction)
throws Exception {
 
String sSql = " select table_name,Column_Name,Data_Type,"
+ " DECODE(DATA_TYPE,'NUMBER',DATA_PRECISION,'VARCHAR2',"
+ " DATA_LENGTH,'VARCHAR',DATA_LENGTH,'CHAR',DATA_LENGTH,0) Length,"
+ " NVL(DATA_SCALE, 0) SCALE,DECODE(NULLABLE, 'N', '1', '0') NULLABLE "
+ " from user_tab_columns where 1=1 Order By table_name,column_name";
 
ASResultSet rs = transaction.getASResultSet(sSql);
 
Map<</SPAN>String, Table> map = new HashMap<</SPAN>String, Table>();
 
String tableName = "";
Table table = null;
while (rs.next()) {
if (!tableName.equals(rs.getString("table_name"))) {// 一张新表
tableName = rs.getString("table_name");
table = new Table(tableName);
Column column = new Column(rs.getString("Column_Name"),
rs.getString("Data_Type"), rs.getInt("Length"));
table.columns.put(column.columnName, column);
map.put(rs.getString("table_name"), table);
} else {// 已存在的表,增加字段
Column column = new Column(rs.getString("Column_Name"),
rs.getString("Data_Type"), rs.getInt("Length"));
table.columns.put(column.columnName, column);
}
}
if (null != rs)
rs.close();
transaction.finalize();
return map;
}
 
 
public static void append(Table table, Column column, int flag)
throws Exception {
switch (flag) {
case 1:
System.out.println("1、生产存在,开发不存在的表:" + table.getTableName());// 跳过
sb[0].append(table.getTableName() + "\n");
break;
case 2:
System.out.println("2、生产不存在,开发存在的表:" + table.getTableName());// 需要人工判断脚本
sb[1].append(table.getTableName() + "\n");
break;
case 3:
System.out.println("3、生产存在,开发不存在的字段:" + table.getTableName()
+ " | " + column.getColumnName());// 需人工判断如何处理
sb[2].append(table.getTableName() + " | " + column.getColumnName()
+ "\n");
break;
case 4:
System.out.println("4、生产不存在,开发存在的字段:" + table.getTableName()
+ " | " + column.getColumnName());// 需要人工判断脚本
sb[3].append(table.getTableName() + " | " + column.getColumnName()
+ "\n");
break;
case 5:
System.out.println("5、表和字段都相同,但字段类型不同的内容:" + table.getTableName()
+ " | " + column.getColumnName() + " | "
+ column.getDataType());// 需要人工判断脚本
sb[4].append(table.getTableName() + " | " + column.getColumnName()
+ " | " + column.getDataType() + "\n");
break;
case 6:
System.out.println("6、表和字段、字段类型都相同,但字段长度不同的内容:"
+ table.getTableName() + " | " + column.getColumnName()
+ " | " + column.getLength());// 需要人工判断脚本
sb[5].append(table.getTableName() + " | " + column.getColumnName()
+ " | " + column.getLength() + "\n");
break;
}
}
 
 
public static void writeFile() throws Exception {
String[] fileName = { "D://table//生产存在,开发不存在的表.txt",
"D://table//生产不存在,开发存在的表.txt", "D://table//生产存在,开发不存在的字段.txt",
"D://table//生产不存在,开发存在的字段.txt",
"D://table//表和字段都相同,但字段类型不同的内容.txt",
"D://table//表和字段、字段类型都相同,但字段长度不同的内容.txt" };
 
for (int i = 0; i <</SPAN> fileName.length; i++) {
File file = new File(fileName[i]);
OutputStream os = new FileOutputStream(file);
os.write(sb[i].toString().getBytes());
os.flush();
os.close();
}
}
}

尾声:整个程序其实并不复杂,感觉被我写得有些累赘了,希望以后能精简一点吧

目录
相关文章
|
10天前
|
DataWorks Oracle 关系型数据库
DataWorks操作报错合集之尝试从Oracle数据库同步数据到TDSQL的PG版本,并遇到了与RAW字段相关的语法错误,该怎么处理
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
28 0
|
1天前
|
SQL Java 数据库连接
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
8 0
|
2天前
|
SQL Java 数据库连接
Java数据库编程实践:连接与操作数据库
Java数据库编程实践:连接与操作数据库
8 0
|
4天前
|
SQL Java 分布式数据库
实现HBase表和RDB表的转化(附Java源码资源)
该文介绍了如何将数据从RDB转换为HBase表,主要涉及三个来源:RDB Table、Client API和Files。文章重点讲解了RDB到HBase的转换,通过批处理思想,利用RDB接口批量导出数据并转化为`List&lt;Put&gt;`,然后导入HBase。目录结构包括配置文件、RDB接口及实现类、HBase接口及实现类,以及一个通用转换器接口和实现。代码中,`RDBImpl`负责从RDB读取数据并构造`Put`对象,`HBaseImpl`则负责将`Put`写入HBase表。整个过程通过配置文件`transfer.properties`管理HBase和RDB的映射关系。
21 3
实现HBase表和RDB表的转化(附Java源码资源)
|
8天前
|
SQL Java 数据库连接
17:数据库连接池与Servlet整合-Java Web
17:数据库连接池与Servlet整合-Java Web
20 3
|
10天前
|
Java 关系型数据库 测试技术
Java代码一键生成数据库文档(案例详解)
Screw是一个自动化数据库文档生成工具,能根据数据库表结构快速生成简洁、多格式(HTML、Word、Markdown)的文档,支持MySQL、MariaDB等多数据库。它使用Freemarker模板,允许用户自定义样式。依赖包括HikariCP数据库连接池和对应JDBC驱动。通过在Java代码或Maven插件中配置,可方便生成文档。示例代码展示了如何在测试用例中使用Screw。文档效果依赖于数据库中的表和字段注释。
|
10天前
|
数据库
数据库字段
数据库字段
|
11天前
|
Java 关系型数据库 MySQL
【JDBC编程】基于MySql的Java应用程序中访问数据库与交互数据的技术
【JDBC编程】基于MySql的Java应用程序中访问数据库与交互数据的技术
|
11天前
|
分布式计算 关系型数据库 大数据
MaxCompute产品使用合集之怎么才可以将 PostgreSQL 中的 geometry 空间类型字段同步到 MaxCompute 或另一个 PostgreSQL 数据库
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
11天前
|
Java 关系型数据库 MySQL
Java基础教程(20)-Java连接mysql数据库CURD
【4月更文挑战第19天】MySQL是流行的关系型数据库管理系统,支持SQL语法。在IDEA中加载jar包到项目类路径:右击项目,选择“Open Module Settings”,添加库文件。使用JDBC连接MySQL,首先下载JDBC驱动,然后通过`Class.forName()`加载驱动,`DriverManager.getConnection()`建立连接。执行CRUD操作,例如创建表、插入数据和查询,使用`Statement`或`PreparedStatement`,并确保正确关闭数据库资源。