Q:R2R(Row-to-Row)映射 XML 是数据同步“源表字段→目标表字段” 的转换规则基础教程。
Posted on 2025-11-18 20:26 三年三班王小朋 阅读(21) 评论(0) 收藏 举报R2R 映射 XML 语法速查表
三、高频表达式模板(直接复用)
Java 风格表达式引擎(支持 body['字段']、三元运算 ? :、.equals(),不支持 SQL 函数)所整理的 R2R(Record-to-Record)映射高频实用模板教程。
所有模板均基于 <column src="..." targ="..." value="..."/> 语法,可直接复制使用,并附带说明和注意事项。
1. 空值或 "-" 转 null
<column src="N/A" targ="目标字段" value='body["源字段"] == null || "-".equals(body["源字段"]) || "".equals(body["源字段"]) ? null : body["源字段"]'/>
2. 代码转名称(值映射)
<column src="N/A" targ="gender" value='"1".equals(body["sex"]) ? "男" : "2".equals(body["sex"]) ? "女" : "未知"'/>
3. 时间标准化(10位补时分秒,19位原样,其他 null)
<column src="N/A" targ="event_time" value='body["date_str"] == null || "-".equals(body["date_str"]) ? null : body["date_str"].length() == 10 ? body["date_str"] + " 00:00:00" : body["date_str"].length() == 19 ? body["date_str"] : null'/>
4. Y/N 转布尔字符串
<column src="N/A" targ="is_valid" value='"Y".equals(body["flag"]) ? "true" : "false"'/>
5. 截取前6位(如身份证地区码)
<column src="N/A" targ="region_code" value='body["id_card"] != null && body["id_card"].length() >= 6 ? body["id_card"].substring(0,6) : null'/>
6. 空值设默认值
<column src="N/A" targ="category" value='body["type"] == null || "".equals(body["type"]) ? "通用" : body["type"]'/>
7. 拼接两字段(安全处理 null)
<column src="N/A" targ="full_name" value='(body["last"] == null ? "" : body["last"]) + (body["first"] == null ? "" : " " + body["first"])'/>
四、基础原则及示例
- 所有字段通过
body['字段名']引用 - 使用单引号包裹整个
value表达式(避免") - 优先用
"常量".equals(body['字段'])防止空指针 - 复杂逻辑用嵌套三元运算模拟
if-else
<table-mapping src="pt_outhosp_order"> <mappings> <mapping targ="yh_mz_yzmxjl" type="all"> <!-- 1. 系统更新时间:将目标表 xtsjgxsj 字段设置为当前系统日期时间 --> <column src="N/A" targ="xtsjgxsj" value="'$(sysdate)'"/> <!-- 2. 操作类型标识:将 dsql_optype 字段设置为 'update',标识操作类型为更新 --> <column src="N/A" targ="dsql_optype" value="'update'"/> <!-- 3. 主键字段映射:将源表 system_source 字段作为主键,映射到目标表 hisbb 字段 --> <column src="system_source" targ="hisbb" pk="true"/> <!-- 4. 操作类型标识:将 dsql_optype 字段设置为 'delete',标识操作类型为删除 --> <column src="N/A" targ="dsql_optype" value="'delete'"/> <!-- 5. 操作类型标识:将 dsql_optype 字段设置为 'batch_delete',标识操作类型为批量删除 --> <column src="N/A" targ="dsql_optype" value="'batch_delete'"/> <!-- 6. 报告流水号构造:通过拼接 request_no 和 report_serial_no 构造目标表 bglsh 字段的值 --> <column src="N/A" targ="bglsh" value="body['request_no']+'_'+body['report_serial_no']"/> <!-- 7. 年龄字段处理:根据 age_unit 的值判断,若为 '1' 或 '岁',则取 age 的值,否则为 null,存入 nls 字段 --> <column src="N/A" targ="nls" value="'1'.equals(body['age_unit'])? body['age']:'岁'.equals(body['age_unit'])? body['age']:null"/> <!-- 8. 就诊性质字段:将目标表 jzxzmc 字段固定设置为 '住院' --> <column src="N/A" targ="jzxzmc" value="'住院'"/> <!-- 9. diag_date源字段三种情况(1:null、2:"-"、3、其他19位时间格式),目标字段时间类型,非必填--> <column src="N/A" targ="zdrqsj" value="body['diag_date'] == null || '-'.equals(body['diag_date']) ? null : body['diag_date']"/> <!-- 10. 如果age源字段可能不存在,目标字段nl字符串类型且必填,值为默认值或者age--> <column src="N/A" targ="nl" value="body['age'] == null ? '18' : body['age']"/> <!-- 11. 如果diag_date源字段可能不存在,目标字段testdt是时间类型且必填,默认值系统时间或者diag_date--> <column src="N/A" targ="testdt" value="body['diag_date'] == null ? '$(sysdate)' : body['diag_date']"/> <!-- 12. 如果diag_date源字段可能不存在,目标字段testdt是时间类型且必填,默认值自定义时间或者diag_date--> <column src="N/A" targ="testdt" value="body['diag_date'] == null ? T(java.time.LocalDate).of(2000,1,1) : T(java.time.LocalDate).parse(body['diag_date'])"/> </mapping> </mappings> </table-mapping> </table-mappings>
五、推测可用的函数表达式
| 类型 | 方法 / 操作 | 示例 | 适用场景 | 推荐表达式写法 |
|---|---|---|---|---|
| 空值判断 | == null |
body["name"] == null |
判断字段是否缺失 | body["字段"] == null |
| 字符串相等 | .equals(String) |
"Y".equals(body["flag"]) |
安全比较字符串值 | 始终将常量放左边,避免 NPE |
| 空字符串判断 | "".equals(...) |
"".equals(body["code"]) |
过滤空字符串 | 与 == null 联用:body["x"] == null || "".equals(body["x"]) |
| 字符串长度 | .length() |
body["id"].length() == 18 |
校验固定长度(如身份证、手机号) | body["字段"].length() == N |
| 截取子串 | .substring(start, end) |
body["date"].substring(0, 4) |
提取年份、地区码、编码段等 | 确保长度足够:len >= end ? str.substring(...) : null |
| 去除空格 | .trim() |
body["name"].trim() |
清洗前后空格 | 常与判空联用:"".equals(body["x"].trim()) |
| 大小写转换 | .toLowerCase() / .toUpperCase() |
body["code"].toLowerCase() |
统一大小写(如匹配、去重) | 一般用于比较前标准化 |
| 前缀判断 | .startsWith(String) |
body["code"].startsWith("A") |
分类、路由、过滤 | body["字段"].startsWith("前缀") |
| 后缀判断 | .endsWith(String) |
body["file"].endsWith(".txt") |
文件类型、状态标识判断 | 同上 |
| 查找子串位置 | .indexOf(String) |
body["email"].indexOf("@") >= 0 |
判断是否包含某字符/子串 | str.indexOf("x") != -1 等价于“包含” |
| 字符串拼接 | + |
body["a"] + "-" + body["b"] |
组合字段(姓名、地址、编码) | 对可能为 null 的字段先转空串:(x == null ? "" : x) + ... |
| 逻辑与 | && |
cond1 && cond2 |
多条件同时成立 | XML 中建议写为 && |
| 逻辑或 | || |
cond1 || cond2 |
多条件任一成立 | XML 中建议写为 &| |
| 逻辑非 | ! |
! "Y".equals(x) |
取反条件 | 常用于排除特定值 |
| 三元条件 | ? : |
x == null ? "默认" : x |
条件赋值、默认值、映射转换 | 支持嵌套,但建议不超过 3 层 |
浙公网安备 33010602011771号