我有两个来自两个不同数据库的结果集,我需要比较它。我想要像
这样的操作A-B
将对他们进行。
我无法逐行比较,因为结果集中的第一行可以出现在B结果集中的任何位置。
下面是在.NET中执行此操作的代码,非常简单和完美。
var nonIntersecting = dtSource.AsEnumerable().Except
(
dtTarget.AsEnumerable(), DataRowComparer.Default
);
try
{
dtSrcToTgtResult = nonIntersecting.CopyToDataTable();
} catch (InvalidOperationException ex) {}
这里dtSource,dtTarget是具有来自数据库的源数据和目标数据的数据表。 dtSrcToTgtResult包含源中但不在目标中的数据,这正是我想要的。
可以在结果集的JavaScript中完成。我还可以检查CachedRowSet
或webRowSet
是否有类似内容。
修改
对于给予减票的人。这就是我已经做过的,但它没有解决问题。
private Boolean compare(ResultSet rsSrc,ResultSet rsTgt,String ExecCondition)
{
Boolean status = true;
try
{
ResultSetMetaData metaSrc = rsSrc.getMetaData();
ResultSetMetaData metaTgt = rsTgt.getMetaData();
final int columnCountSrc = metaSrc.getColumnCount();
List<DBRow> dList = new ArrayList<DBRow>();
List<DBRow> DataInSourceNotInTarget = new ArrayList<DBRow>();
List<DBRow> DataInTargetNotInSource = new ArrayList<DBRow>();
DBRow d = new DBRow();
DBRow d1 = new DBRow();
for (int column = 1; column <= columnCountSrc; column++)
{
d.Row.add(metaSrc.getColumnName(column));
d1.Row.add(metaTgt.getColumnName(column));
}
DataInSourceNotInTarget.add(d);
DataInTargetNotInSource.add(d1);
if(ExecCondition.equals("Source To Target"))
{
while(rsSrc.next())
{
if(rsTgt.next())
{
for (int column = 1; column <= columnCountSrc; column++)
{
Object valueSrc = rsSrc.getObject(column);
Object valueTgt = rsTgt.getObject(column);
if(!valueSrc.toString().equals(valueTgt.toString()))
{
status=false;
System.out.println("ValueSRC: "+v alueSrc.toString());
System.out.println("ValueTgt: "+valueTgt.toString());
}
}
}
else
{
// if target rows ends
DBRow dr = new DBRow();
for (int column = 1; column <= columnCountSrc; column++)
{
Object valueSrc = rsSrc.getObject(column);
dr.Row.add(valueSrc);
}
DataInSourceNotInTarget.add(dr);
}
}
}//exec condition if
if(ExecCondition.equals("Target To Source"))
{
while(rsTgt.next())
{
if(rsSrc.next())
{
for (int column = 1; column <= columnCountSrc; column++)
{
Object valueSrc = rsSrc.getObject(column);
Object valueTgt = rsTgt.getObject(column);
if(!valueSrc.toString().equals(valueTgt.toString()))
{
status=false;
System.out.println("ValueSRC: "+valueSrc.toString());
System.out.println("ValueTgt: "+valueTgt.toString());
}
}
}
else
{
// if Source rows ends
DBRow dr = new DBRow();
for (int column = 1; column <= columnCountSrc; column++)
{
Object valueTgt = rsTgt.getObject(column);
dr.Row.add(valueTgt);
}
DataInTargetNotInSource.add(dr);
}
}
for(DBRow obj:DataInTargetNotInSource)
{
obj.print();
}
}//exec condition if
}
catch(Exception e)
{
e.printStackTrace();
}
return status;
}
答案 0 :(得分:2)
我有一个功能但不是最佳的解决方案:
我使用Apache DbUtils轻松地将ResultSet转换为List。
import java.sql.*;
import java.util.*;
import java.util.stream.*;
import org.apache.commons.dbutils.handlers.MapListHandler;
try (Connection conn = DriverManager.getConnection(url, user, password)) {
// load source table
Statement st = conn.createStatement();
ResultSet sourceRs = st.executeQuery("SELECT * FROM source");
List<Map<String, Object>> sourceRows = new MapListHandler().handle(sourceRs);
sourceRs.close();
st.close();
// load target table
st = conn.createStatement();
ResultSet targetRs = st.executeQuery("SELECT * FROM target");
List<Map<String, Object>> targetRows = new MapListHandler().handle(targetRs);
targetRs.close();
st.close();
// for every row in source, look for no match in target
List<Map<String, Object>> diffRows =
sourceRows.stream()
.filter(sourceRow -> rowExistsInTable(sourceRow, targetRows) == false)
.collect(Collectors.toList());
diffRows.stream().forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
}
编辑:
您会注意到sourceRows
的过滤现在是根据方法rowExistsInTable()
的结果完成的。我添加了在表中搜索行的方法,并检查行的相等性,而不依赖于java 8 lambda语法(还添加了尽可能多的文档:))
/**
* checks if {@code searchRow} exists in {@code table}
* existence is determined according to {@code areRowsEqual} method
* @param searchRow {@code Map<String, Object>} where keys are column names and values are column vales
* @param table {@code List} of {@code Map<String, Object>} rows
* @return {@code true} if {@code searchRow} was found in {@code table}
*/
public static boolean rowExistsInTable(Map<String, Object> searchRow, List<Map<String, Object>> table)
{
for (Map<String, Object> tableRow : table) {
if (areRowsEqual(tableRow, searchRow)) return true;
}
return false;
}
/**
* checks if all of row1 columns are found with same values in row2
* note: does not check if there is column in row2 that does not exist in row1
* @param row1
* @param row2
* @return {@code true} if {@code row1} is equal to {@code row2}
*/
public static boolean areRowsEqual(Map<String, Object> row1, Map<String, Object> row2)
{
// loop on row1 columns
for (Map.Entry<String, Object> row1Column : row1.entrySet()) {
String row1ColumnName = row1Column.getKey();
Object row1ColumnValue = row1Column.getValue();
// search row1 column in row2
if (row2.containsKey(row1ColumnName) &&
row2.get(row1ColumnName) != null &&
row2.get(row1ColumnName).equals(row1ColumnValue)) {
// row1 column was found in row2, nothing to do
} else {
// row1 column was not found in row2
return false;
}
}
return true; // all row 1 columns found in row 2
}