一、两个数据同步模型全景分析
案例1:InStorageSync(OUT方向 --- 定时输出同步)
业务场景 :供应链入库实体(Supply_Chain_Mgmt.IN_STORAGE) 每天定时将入库数据按仓库位置分组导出CSV文件,通过FTP回写到外部系统。
关联模型关系图
#mermaid-svg-ZfXUZSWNdW07naM1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZfXUZSWNdW07naM1 .error-icon{fill:#552222;}#mermaid-svg-ZfXUZSWNdW07naM1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZfXUZSWNdW07naM1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 .marker.cross{stroke:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZfXUZSWNdW07naM1 p{margin:0;}#mermaid-svg-ZfXUZSWNdW07naM1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster-label text{fill:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster-label span{color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster-label span p{background-color:transparent;}#mermaid-svg-ZfXUZSWNdW07naM1 .label text,#mermaid-svg-ZfXUZSWNdW07naM1 span{fill:#333;color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .node rect,#mermaid-svg-ZfXUZSWNdW07naM1 .node circle,#mermaid-svg-ZfXUZSWNdW07naM1 .node ellipse,#mermaid-svg-ZfXUZSWNdW07naM1 .node polygon,#mermaid-svg-ZfXUZSWNdW07naM1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .rough-node .label text,#mermaid-svg-ZfXUZSWNdW07naM1 .node .label text,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape .label,#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZfXUZSWNdW07naM1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .rough-node .label,#mermaid-svg-ZfXUZSWNdW07naM1 .node .label,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape .label,#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape .label{text-align:center;}#mermaid-svg-ZfXUZSWNdW07naM1 .node.clickable{cursor:pointer;}#mermaid-svg-ZfXUZSWNdW07naM1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 .arrowheadPath{fill:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZfXUZSWNdW07naM1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZfXUZSWNdW07naM1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZfXUZSWNdW07naM1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZfXUZSWNdW07naM1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZfXUZSWNdW07naM1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster text{fill:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster span{color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZfXUZSWNdW07naM1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape p,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape .label rect,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZfXUZSWNdW07naM1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZfXUZSWNdW07naM1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZfXUZSWNdW07naM1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 处理逻辑 PSDELOGIC
后端插件 PSSYSSFPLUGIN
系统数据同步代理 PSSYSDATASYNCAGENT
导出表格 PSDEGRID
数据导出 PSDEDATAEXP
输出数据集 PSDEDATASET
实体数据同步 PSDEDATASYNC
所属实体 PSDATAENTITY
psdeid
psdeid
psdeid
psdeid
outpsdedatasetid
outpssysdatasyncagentid
psdedataexpid
pssyssfpluginid
psdegridid
psdelogicid
filtermodel.groupFields=stor_location
Supply_Chain_Mgmt.IN_STORAGE
入库实体
InStorageSync
入库数据输出同步
syncdir=OUT
outmode=2(定时)
eventtype=7(新建+更新+删除)
timerpolicy=定时CRON
SyncInStorageToSAP
入库数据导出数据集
predefinedtype=DELOGIC
基于处理逻辑的数据集
InStorageSync
入库数据导出
contenttype=CSV
filenameformat=带时间戳的CSV文件
InStorageExportSync
导出列定义
FTPOutputAgent
FTP回写代理
agenttype=FILE
syncdir=OUT
servicepath=外部FTP路径
GroupDEDataSyncOutRuntime
分组数据同步输出运行时
SyncInStorageToSAPLogic
提供数据集查询逻辑
DSL代码解析
groovy
// PSDEDATASYNC - 实体数据同步
psdedatasync(
name: "入库数据输出同步",
codename: "InStorageSync",
outmode: 2, // 定时输出
eventtype: 7, // 新建1+更新2+删除4=7(全事件)
filtermodel: "{\"groupFields\":\"stor_location\",\"afterDEAction\":\"SyncInStorageToSAPExport\"}",
memo: "[业务编码]",
outpsdedatasetid: "Supply_Chain_Mgmt.IN_STORAGE.SyncInStorageToSAP", // 输出数据集
outpssysdatasyncagentid: "System_Mgmt.FTPOutputAgent", // 输出代理
psdedataexpid: "Supply_Chain_Mgmt.IN_STORAGE.InStorageSync", // 数据导出
psdeid: "Supply_Chain_Mgmt.IN_STORAGE", // 所属实体
pssyssfpluginid: "GroupDEDataSyncOutRuntime", // 后端插件(分组输出)
syncdir: "OUT", // 输出方向
timerpolicy: "定时CRON表达式" // 每天定时执行
)
// PSSYSDATASYNCAGENT - 系统数据同步代理(FTP输出)
pssysdatasyncagent(
name: "FTP回写代理",
codename: "FTPOutputAgent",
agenttype: "FILE", // 文件类型代理
authclientid: "认证客户端ID",
authclientsecret: "认证密钥",
authmode: "PASSWORD",
psmoduleid: "System_Mgmt",
servicepath: "外部FTP服务路径", // FTP目标地址
syncdir: "OUT" // 输出方向
)
// PSDEDATAEXP - 数据导出(CSV格式)
psdedataexp(
name: "入库数据导出",
codename: "InStorageSync",
filenameformat: "前缀_{#date_fmt.format('yyyyMMddHHmmss')}.csv",
contenttype: "CSV",
defaultflag: 0,
psdegridid: "Supply_Chain_Mgmt.IN_STORAGE.InStorageExportSync", // 导出表格
psdeid: "Supply_Chain_Mgmt.IN_STORAGE"
)
// PSDEDATASET - 输出数据集(基于处理逻辑)
psdedataset(
name: "SyncInStorageToSAP",
codename: "SyncInStorageToSAP",
logicname: "入库数据导出数据集",
psdeid: "Supply_Chain_Mgmt.IN_STORAGE",
psdelogicid: "Supply_Chain_Mgmt.IN_STORAGE.SyncInStorageToSAPLogic", // 关联处理逻辑
predefinedtype: "DELOGIC" // 基于处理逻辑
)
案例2:InboundSync(IN方向 --- 定时输入同步)
业务场景 :对账实体(Statement_Mgmt.STATEMENTENTITY) 每天定时从外部系统共享文件夹读取指定模式文件,通过TSV格式导入解析,调用批量导入行为写入数据库。
关联模型关系图
#mermaid-svg-skhIumX3DxYSKMam{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-skhIumX3DxYSKMam .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-skhIumX3DxYSKMam .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-skhIumX3DxYSKMam .error-icon{fill:#552222;}#mermaid-svg-skhIumX3DxYSKMam .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-skhIumX3DxYSKMam .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-skhIumX3DxYSKMam .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-skhIumX3DxYSKMam .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-skhIumX3DxYSKMam .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-skhIumX3DxYSKMam .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-skhIumX3DxYSKMam .marker{fill:#333333;stroke:#333333;}#mermaid-svg-skhIumX3DxYSKMam .marker.cross{stroke:#333333;}#mermaid-svg-skhIumX3DxYSKMam svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-skhIumX3DxYSKMam p{margin:0;}#mermaid-svg-skhIumX3DxYSKMam .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster-label text{fill:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster-label span{color:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster-label span p{background-color:transparent;}#mermaid-svg-skhIumX3DxYSKMam .label text,#mermaid-svg-skhIumX3DxYSKMam span{fill:#333;color:#333;}#mermaid-svg-skhIumX3DxYSKMam .node rect,#mermaid-svg-skhIumX3DxYSKMam .node circle,#mermaid-svg-skhIumX3DxYSKMam .node ellipse,#mermaid-svg-skhIumX3DxYSKMam .node polygon,#mermaid-svg-skhIumX3DxYSKMam .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .rough-node .label text,#mermaid-svg-skhIumX3DxYSKMam .node .label text,#mermaid-svg-skhIumX3DxYSKMam .image-shape .label,#mermaid-svg-skhIumX3DxYSKMam .icon-shape .label{text-anchor:middle;}#mermaid-svg-skhIumX3DxYSKMam .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .rough-node .label,#mermaid-svg-skhIumX3DxYSKMam .node .label,#mermaid-svg-skhIumX3DxYSKMam .image-shape .label,#mermaid-svg-skhIumX3DxYSKMam .icon-shape .label{text-align:center;}#mermaid-svg-skhIumX3DxYSKMam .node.clickable{cursor:pointer;}#mermaid-svg-skhIumX3DxYSKMam .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-skhIumX3DxYSKMam .arrowheadPath{fill:#333333;}#mermaid-svg-skhIumX3DxYSKMam .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-skhIumX3DxYSKMam .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-skhIumX3DxYSKMam .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-skhIumX3DxYSKMam .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-skhIumX3DxYSKMam .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-skhIumX3DxYSKMam .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-skhIumX3DxYSKMam .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .cluster text{fill:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster span{color:#333;}#mermaid-svg-skhIumX3DxYSKMam div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-skhIumX3DxYSKMam .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-skhIumX3DxYSKMam rect.text{fill:none;stroke-width:0;}#mermaid-svg-skhIumX3DxYSKMam .icon-shape,#mermaid-svg-skhIumX3DxYSKMam .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-skhIumX3DxYSKMam .icon-shape p,#mermaid-svg-skhIumX3DxYSKMam .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-skhIumX3DxYSKMam .icon-shape .label rect,#mermaid-svg-skhIumX3DxYSKMam .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-skhIumX3DxYSKMam .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-skhIumX3DxYSKMam .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-skhIumX3DxYSKMam :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 后端插件 PSSYSSFPLUGIN
实体行为 PSDEACTION
系统数据同步代理 PSSYSDATASYNCAGENT
数据导入 PSDEDATAIMP
实体数据同步 PSDEDATASYNC
所属实体 PSDATAENTITY
psdeid
psdeid
psdeid
inpssysdatasyncagentid
psdedataimpid
createpsdeactionid
pssyssfpluginid
filtermodel.file=文件匹配模式
包含
导入项映射(多项)
vendor_do_no -> VENDOR_DO_NO
customer_po_no -> CUSTOMER_PO_NO
product_code -> PRODUCT_CODE
entry_quantity -> ENTRY_QUANTITY
entry_amount -> ENTRY_AMOUNT
... 共多个字段映射
Statement_Mgmt.STATEMENTENTITY
对账实体
InboundSync
入库数据同步
syncdir=IN
eventtype=7
timerpolicy=定时CRON
filtermodel={file:文件匹配模式}
Inbound
入库数据同步
contenttype=TSV
stopwhenerror=0
enablecustomized=1
FileInputAgent
文件输入代理
agenttype=FILE
syncdir=IN
servicepath=外部共享路径
StatementBatchImport
批量导入行为
CustomDEDataImportRuntime
自定义数据导入运行时
DSL代码解析
groovy
// PSDEDATASYNC - 实体数据同步(输入)
psdedatasync(
name: "入库数据同步",
codename: "InboundSync",
eventtype: 7, // 全事件
filtermodel: "{\"file\":\"文件匹配模式\"}", // 文件过滤模式
inpssysdatasyncagentid: "System_Mgmt.FileInputAgent", // 输入代理
memo: "[业务编码]实现从文件提取后的临时表数据导入...",
psdedataimpid: "Statement_Mgmt.STATEMENTENTITY.Inbound", // 数据导入
psdeid: "Statement_Mgmt.STATEMENTENTITY",
syncdir: "IN", // 输入方向
timerpolicy: "定时CRON表达式" // 每天定时执行
)
// PSSYSDATASYNCAGENT - 系统数据同步代理(文件输入)
pssysdatasyncagent(
name: "文件输入代理",
codename: "FileInputAgent",
agenttype: "FILE", // 文件类型代理
psmoduleid: "System_Mgmt",
servicepath: "外部共享文件路径",
syncdir: "IN" // 输入方向
)
// PSDEDATAIMP - 数据导入(TSV格式,含多个字段映射)
psdedataimp(
name: "入库数据同步",
codename: "Inbound",
contenttype: "TSV", // TSV格式
createpsdeactionid: "Statement_Mgmt.STATEMENTENTITY.StatementBatchImport", // 批量导入行为
defaultflag: 0,
enablecustomized: 1, // 支持定制
psdeid: "Statement_Mgmt.STATEMENTENTITY",
pssyssfpluginid: "CustomDEDataImportRuntime", // 自定义导入运行时
stopwhenerror: 0 // 出错不中止
){
// 多个导入字段映射(示例部分)
psdedataimpitem(id: "vendor_do_no", name: "vendor_do_no", caption: "Vendor DO No.", keyflag: 0, ordervalue: 1, psdefid: "Statement_Mgmt.STATEMENTENTITY.VENDOR_DO_NO")
psdedataimpitem(id: "product_code", name: "product_code", caption: "Material", keyflag: 0, ordervalue: 8, psdefid: "Statement_Mgmt.STATEMENTENTITY.PRODUCT_CODE")
psdedataimpitem(id: "entry_quantity", name: "entry_quantity", caption: "Quantity", keyflag: 0, ordervalue: 10, psdefid: "Statement_Mgmt.STATEMENTENTITY.ENTRY_QUANTITY")
psdedataimpitem(id: "purchasing_document", name: "purchasing_document", caption: "Purchasing Doc.", keyflag: 1, ordervalue: 32, psdefid: "Statement_Mgmt.STATEMENTENTITY.PURCHASING_DOCUMENT")
// ... 其余字段省略
}
二、PSDEDATASYNC 完整关联模型体系
基于上述两个案例及模型架构定义,实体数据同步涉及的核心模型及关联关系如下:
2.1 模型关系总览
#mermaid-svg-V1PK0lnFlIIuBxEd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-V1PK0lnFlIIuBxEd .error-icon{fill:#552222;}#mermaid-svg-V1PK0lnFlIIuBxEd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-V1PK0lnFlIIuBxEd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd .marker.cross{stroke:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-V1PK0lnFlIIuBxEd p{margin:0;}#mermaid-svg-V1PK0lnFlIIuBxEd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster-label text{fill:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster-label span{color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster-label span p{background-color:transparent;}#mermaid-svg-V1PK0lnFlIIuBxEd .label text,#mermaid-svg-V1PK0lnFlIIuBxEd span{fill:#333;color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .node rect,#mermaid-svg-V1PK0lnFlIIuBxEd .node circle,#mermaid-svg-V1PK0lnFlIIuBxEd .node ellipse,#mermaid-svg-V1PK0lnFlIIuBxEd .node polygon,#mermaid-svg-V1PK0lnFlIIuBxEd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .rough-node .label text,#mermaid-svg-V1PK0lnFlIIuBxEd .node .label text,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape .label,#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape .label{text-anchor:middle;}#mermaid-svg-V1PK0lnFlIIuBxEd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .rough-node .label,#mermaid-svg-V1PK0lnFlIIuBxEd .node .label,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape .label,#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape .label{text-align:center;}#mermaid-svg-V1PK0lnFlIIuBxEd .node.clickable{cursor:pointer;}#mermaid-svg-V1PK0lnFlIIuBxEd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd .arrowheadPath{fill:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-V1PK0lnFlIIuBxEd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-V1PK0lnFlIIuBxEd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V1PK0lnFlIIuBxEd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-V1PK0lnFlIIuBxEd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V1PK0lnFlIIuBxEd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster text{fill:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster span{color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-V1PK0lnFlIIuBxEd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd rect.text{fill:none;stroke-width:0;}#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape p,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape .label rect,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V1PK0lnFlIIuBxEd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-V1PK0lnFlIIuBxEd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-V1PK0lnFlIIuBxEd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 调度策略
事件监控
实体层
输入侧(IN方向)
输出侧(OUT方向)
数据代理
方向决定
核心:PSDEDATASYNC
outpssysdatasyncagentid
outpsdedatasetid
psdedataexpid
pssyssfpluginid
psdegridid
inpssysdatasyncagentid
psdedataimpid
createpsdeactionid
pssyssfpluginid
包含
psdeid
psdelogicid
psdedqid
eventtype
timerpolicy
实体数据同步
psdedatasync
IN(输入)
从外部接收数据
OUT(输出)
向外部发送数据
PSSYSDATASYNCAGENT
系统数据同步代理
-
FILE/KAFKA/RABBITMQ/...
-
IN/OUT/INOUT
PSDEDATASET
输出数据集
定义输出数据范围
PSDEDATAEXP
数据导出
CSV/TSV/XLSX/JSON
PSDEGRID
导出表格
定义导出列
PSSYSSFPLUGIN
后端插件
GroupDEDataSyncOutRuntime
PSDEDATAIMP
数据导入
含导入项映射
PSDEDATAIMPITEM
导入字段映射
多个字段
PSDEACTION
导入行为
批量导入
PSSYSSFPLUGIN
后端插件
CustomDEDataImportRuntime
PSDATAENTITY
所属实体
PSDEDATAQUERY
数据查询
PSDELOGIC
处理逻辑
(数据集来源)
eventtype
1-新建 2-更新 4-删除
7=全部
timerpolicy
CRON表达式
outmode=1实时/2定时
2.2 关键属性说明
| 属性 | 说明 | 案例1(InStorageSync) | 案例2(InboundSync) |
|---|---|---|---|
syncdir |
同步方向:IN/OUT | OUT |
IN |
eventtype |
监控事件:1新建/2更新/4删除/7全部 | 7 |
7 |
outmode |
输出模式:1实时/2定时 | 2(定时) |
- |
timerpolicy |
CRON定时策略 | 定时CRON表达式 | 定时CRON表达式 |
filtermodel |
过滤器模型(JSON) | {"groupFields":"stor_location",...} |
{"file":"文件匹配模式"} |
pssyssfpluginid |
后端运行时插件 | GroupDEDataSyncOutRuntime |
- |
三、标准构建指南
3.1 构建步骤总览
#mermaid-svg-UoqBgqGIp6Za2h39{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UoqBgqGIp6Za2h39 .error-icon{fill:#552222;}#mermaid-svg-UoqBgqGIp6Za2h39 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UoqBgqGIp6Za2h39 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 .marker.cross{stroke:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UoqBgqGIp6Za2h39 p{margin:0;}#mermaid-svg-UoqBgqGIp6Za2h39 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster-label text{fill:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster-label span{color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster-label span p{background-color:transparent;}#mermaid-svg-UoqBgqGIp6Za2h39 .label text,#mermaid-svg-UoqBgqGIp6Za2h39 span{fill:#333;color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .node rect,#mermaid-svg-UoqBgqGIp6Za2h39 .node circle,#mermaid-svg-UoqBgqGIp6Za2h39 .node ellipse,#mermaid-svg-UoqBgqGIp6Za2h39 .node polygon,#mermaid-svg-UoqBgqGIp6Za2h39 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .rough-node .label text,#mermaid-svg-UoqBgqGIp6Za2h39 .node .label text,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape .label,#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape .label{text-anchor:middle;}#mermaid-svg-UoqBgqGIp6Za2h39 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .rough-node .label,#mermaid-svg-UoqBgqGIp6Za2h39 .node .label,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape .label,#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape .label{text-align:center;}#mermaid-svg-UoqBgqGIp6Za2h39 .node.clickable{cursor:pointer;}#mermaid-svg-UoqBgqGIp6Za2h39 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 .arrowheadPath{fill:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UoqBgqGIp6Za2h39 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UoqBgqGIp6Za2h39 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UoqBgqGIp6Za2h39 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UoqBgqGIp6Za2h39 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UoqBgqGIp6Za2h39 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster text{fill:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster span{color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UoqBgqGIp6Za2h39 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 rect.text{fill:none;stroke-width:0;}#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape p,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape .label rect,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UoqBgqGIp6Za2h39 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UoqBgqGIp6Za2h39 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UoqBgqGIp6Za2h39 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OUT(输出)
IN(输入)
Step 1: 明确业务需求
Step 2: 确定同步方向
IN or OUT?
Step 3: 定义数据代理
PSSYSDATASYNCAGENT
Step 3: 定义数据代理
PSSYSDATASYNCAGENT
Step 4: 定义输出数据集
PSDEDATASET
Step 4: 定义数据导入
PSDEDATAIMP + 导入项
Step 5: 定义数据导出
PSDEDATAEXP + 导出表格
Step 5: 定义导入行为
PSDEACTION
Step 6: 定义实体数据同步
PSDEDATASYNC
Step 7: 编译验证 & 构建
3.2 输出同步(OUT方向)构建模板
groovy
// ========== Step 1: 定义系统数据同步代理 ==========
pssysdatasyncagent(
name: "XXX输出代理",
codename: "XXXOutput",
agenttype: "FILE", // FILE/KAFKA/RABBITMQ/...
psmoduleid: "System_Mgmt", // 所属模块
servicepath: "外部目标路径", // 目标路径
syncdir: "OUT", // 输出方向
// 文件类型可配置:
// rawdatamode: 1, // 直接数据模式(不附加包头)
// topic: "topic_name" // 消息队列主题
)
// ========== Step 2: 定义输出数据集 ==========
// 方式A:基于处理逻辑
psdedataset(
name: "SyncToXXX",
codename: "SyncToXXX",
logicname: "XXX导出数据集",
psdeid: "Module.Entity",
psdelogicid: "Module.Entity.SyncToXXXLogic", // 处理逻辑提供查询
predefinedtype: "DELOGIC"
)
// 方式B:基于数据查询
// psdedataset(
// name: "SyncToXXX",
// codename: "SyncToXXX",
// psdeid: "Module.Entity",
// psdedqid: "Module.Entity.DefaultQuery"
// )
// ========== Step 3: 定义数据导出 ==========
psdedataexp(
name: "XXX数据导出",
codename: "SyncToXXX",
contenttype: "CSV", // CSV/TSV/XLSX/JSON
filenameformat: "前缀_{#date_fmt.format('yyyyMMddHHmmss')}.csv",
psdegridid: "Module.Entity.ExportGrid", // 导出表格(定义导出列)
psdeid: "Module.Entity"
)
// ========== Step 4: 定义实体数据同步 ==========
psdedatasync(
name: "XXX输出同步",
codename: "SyncToXXX",
syncdir: "OUT", // 输出方向
eventtype: 7, // 新建+更新+删除
outmode: 2, // 2=定时输出
timerpolicy: "定时CRON表达式", // CRON定时策略
outpsdedatasetid: "Module.Entity.SyncToXXX", // 输出数据集
outpssysdatasyncagentid: "System_Mgmt.XXXOutput", // 输出代理
psdedataexpid: "Module.Entity.SyncToXXX", // 数据导出
psdeid: "Module.Entity", // 所属实体
pssyssfpluginid: "GroupDEDataSyncOutRuntime", // 分组输出插件
filtermodel: "{\"groupFields\":\"field_name\"}" // 分组字段(可选)
)
3.3 输入同步(IN方向)构建模板
groovy
// ========== Step 1: 定义系统数据同步代理 ==========
pssysdatasyncagent(
name: "XXX输入代理",
codename: "XXXInput",
agenttype: "FILE", // FILE/KAFKA/RABBITMQ/...
psmoduleid: "System_Mgmt",
servicepath: "外部共享文件路径", // 源路径
syncdir: "IN", // 输入方向
// 消息队列场景:
// groupid: "consumer_group", // 消费组
// topic: "topic_name"
)
// ========== Step 2: 定义实体导入行为 ==========
// 需先定义实体的批量导入行为 PSDEACTION
// ========== Step 3: 定义数据导入 ==========
psdedataimp(
name: "XXX数据导入",
codename: "XXXImport",
contenttype: "TSV", // CSV/TSV/XLSX/JSON
createpsdeactionid: "Module.Entity.BatchImport", // 批量导入行为
stopwhenerror: 0, // 出错不中止
enablecustomized: 1, // 支持定制
psdeid: "Module.Entity",
pssyssfpluginid: "CustomDEDataImportRuntime" // 自定义导入插件
){
// 导入字段映射(每个字段对应一个实体属性)
psdedataimpitem(
id: "field_code",
name: "field_code",
caption: "字段标题",
keyflag: 0, // 1=识别属性(用于判断新建或更新)
ordervalue: 1,
psdefid: "Module.Entity.FIELD_NAME"
)
// ... 更多字段
}
// ========== Step 4: 定义实体数据同步 ==========
psdedatasync(
name: "XXX输入同步",
codename: "XXXInputSync",
syncdir: "IN", // 输入方向
eventtype: 7, // 全事件
inpssysdatasyncagentid: "System_Mgmt.XXXInput", // 输入代理
psdedataimpid: "Module.Entity.XXXImport", // 数据导入
psdeid: "Module.Entity", // 所属实体
filtermodel: "{\"file\":\"文件匹配模式\"}", // 文件过滤模式
timerpolicy: "定时CRON表达式" // 每天定时执行
)
3.4 关键设计要点
| 设计维度 | 说明 |
|---|---|
| 同步方向 | syncdir=IN为输入(从外部接收),OUT为输出(向外部发送) |
| 事件类型 | eventtype按位组合:新建=1、更新=2、删除=4,全事件=7 |
| 输出模式 | outmode=1实时触发 / outmode=2定时触发(需配置timerpolicy) |
| 数据代理类型 | agenttype支持 FILE(文件)、KAFKA、RABBITMQ、FTP、SFTP、SMB、INTERNAL(内部通讯)等 |
| 文件过滤 | IN方向通过filtermodel的file属性指定文件名匹配模式 |
| 分组输出 | OUT方向通过filtermodel的groupFields指定分组字段,实现按字段分组输出多个文件 |
| 后端插件 | 输出同步常用GroupDEDataSyncOutRuntime,输入同步常用CustomDEDataImportRuntime |
| 导入识别 | 导入项keyflag=1标记识别属性,系统根据识别属性判断新建还是更新 |
| CRON表达式 | 格式:秒 分 时 日 月 周 年,如定时CRON表达式 |
3.5 典型应用场景对照
| 场景 | 方向 | 代理类型 | 数据格式 | 插件 | 案例参考 |
|---|---|---|---|---|---|
| 外部文件回写 | OUT | FILE(FTP) | CSV | GroupDEDataSyncOutRuntime | InStorageSync |
| 外部文件读取 | IN | FILE(SMB) | TSV | CustomDEDataImportRuntime | InboundSync |
| 消息队列发送 | OUT | KAFKA | JSON | - | - |
| 消息队列消费 | IN | KAFKA | JSON | - | - |
| 内部组件通讯 | INOUT | INTERNAL | - | - | - |