SymmetricDS运行时新增列出现列数不匹配错误如何正确处理
SymmetricDS异构表结构同步字段赋值解决方案
报错原因
你遇到的报错是因为在beforeWrite阶段直接修改了同步协议解析出来的Table元数据对象,该对象的列数和原始CSV数据的字段数是强绑定校验的,手动新增列会触发元数据和实际数据的一致性校验失败。
正确实现方式
所有修改逻辑需要在服务端的写入过滤器中执行,不要动态修改同步协议携带的原始表元数据,优先读取服务端本地已存在的目标表结构做适配:
- 提前在服务端创建好包含所有新增列的目标表结构,不要在同步流程中动态改表
- 重写
DatabaseWriterFilterAdapter的beforeWrite方法,参考以下代码实现:
import org.jumpmind.symmetric.io.data.DataContext; import org.jumpmind.symmetric.io.data.CsvData; import org.jumpmind.symmetric.io.data.writer.DatabaseWriterFilterAdapter; import org.jumpmind.db.model.Table; import java.util.Arrays; @Override public boolean beforeWrite(DataContext context, Table originalTable, CsvData data) { // 读取原始行数据 String[] originalRowData = data.getParsedData(CsvData.ROW_DATA); // 步骤1:清空指定原有列的值,比如示例中的A列 int columnAIndex = originalTable.getColumnIndex("A"); if (columnAIndex >= 0) { originalRowData[columnAIndex] = null; } // 步骤2:读取服务端本地的完整目标表元数据 Table targetTable = context.getPlatform().getTableFromCache( originalTable.getCatalog(), originalTable.getSchema(), originalTable.getName(), false ); // 扩容原始数据数组到服务端表的列数 String[] newRowData = Arrays.copyOf(originalRowData, targetTable.getColumnCount()); // 给服务端新增的B列赋值 int columnBIndex = targetTable.getColumnIndex("B"); if (columnBIndex >= 0) { newRowData[columnBIndex] = "NEWTEXT"; } // 更新数据和上下文元数据 data.removeAllData(CsvData.ROW_DATA); data.putParsedData(CsvData.ROW_DATA, newRowData); context.setTable(targetTable); return true; }
额外配置注意
- 在服务端sym参数配置中添加
data.loader.ignore.missing.columns=true,避免客户端少传列时提前触发校验错误 - 如果需要覆盖insert场景的字段值,同步修改
CsvData.OLD_DATA对应位置的数值即可 - 列名大小写需要和数据库实际存储的列名保持一致,避免获取索引为-1导致赋值失败
内容的提问来源于stack exchange,提问作者Emanuele
相关产品推荐
相关产品推荐

