[BUG] 2.7.3 分支 DeviceMapper.update 的 SQL 缺少空格,库中存在在线设备时启动必失败
环境信息:
- 部署方式 wvp-pro docker(Dockerfile 内 git clone 后 checkout 2.7.3 自行编译)
- 部署环境 ubuntu (docker)
- 端口开放情况 3000 / 5060(tcp+udp),host 网络
- 是否是公网部署 是
- 是否使用https 否
- 接入设备/平台品牌 GB28181 摄像机
- 你做过哪些尝试 已定位到 SQL 渲染结果,并与 master 对比确认该问题在 master 已修复
- 代码更新时间 2.7.3 分支 b1ff1ef(2025-05-26)
- 是否是4G设备接入 否
描述错误
2.7.3 分支 DeviceMapper.update 中,", server_id=#{serverId}" 与 "WHERE device_id=#{deviceId}"
之间缺少空格。这两段在 Java 编译期即被拼接为同一段静态文本,中间没有 <if>/</if> 标签边界,
MyBatis 的 DynamicContext(3.5.9 为 StringJoiner(" "))无法补入空格,最终渲染为:
..., server_id=?WHERE device_id=?PostgreSQL 报错(serverId 恰为第 22 个参数):
org.postgresql.util.PSQLException: ERROR: trailing junk after parameter at or near "$22WHERE"引入点为 b0b5a0f5(2025-05-22),该提交将这段 UPDATE 的 <if> 条件全部移除、改为无条件 SET;
此前写法是 "<if test=\"serverId != null\">, server_id=#{serverId}</if>",</if> 提供了标签边界故不受影响。
该行已由 3845c032(2025-05-29)在 master 修复,但 2.7.3 分支最后一次提交停在 b1ff1ef(2025-05-26),
比修复早 3 天,因此修复未进入 2.7.3。目前 2.7.3 与 dev/1400 仍带有此问题。
影响
SipRunner(@Order(14))在启动时遍历 getAllOnlineDevice() 并调用
deviceService.online()/offline() → deviceMapper.update(),因此:
wvp_device中没有on_line=true记录时启动正常(循环不执行),问题不可见;- 一旦有设备被记录为在线,此后每次启动都会
Application run failed; 容器若配置restart: always即进入无限重启。
此外 SIP 监听在 SipLayer(@Order(10))先于 SipRunner 建立,且工程内没有
@PreDestroy / stopStack,上下文关闭后端口仍在接收 REGISTER,因此会持续刷出:
java.lang.IllegalStateException: LettuceConnectionFactory was destroyed and cannot be used anymore
at ...RedisCatchStorageImpl.getDevice(RedisCatchStorageImpl.java:174)
at ...RegisterRequestProcessor.process(RegisterRequestProcessor.java:93)运行期同样受影响:已存在设备的注册续订、心跳超时下线都会走 update(),
异常为 BadSqlGrammarException(RuntimeException),不在
RegisterRequestProcessor.process 的 catch 列表内,被 @Async 默认处理器吞掉,
表现为设备在线状态静默不再刷新。
如何复现
- 用 2.7.3 分支编译部署,数据库使用 PostgreSQL
- 让任意一台国标设备注册成功(首次注册走
deviceMapper.add,SQL 正常,库中写入on_line=true) - 重启 wvp
- 启动即失败
也可直接在 PostgreSQL 上验证语法:
PREPARE t AS UPDATE wvp_device SET server_id=$1WHERE device_id=$2;
-- ERROR: trailing junk after parameter at or near "$1WHERE"
PREPARE t2 AS UPDATE wvp_device SET server_id=$1 WHERE device_id=$2;
-- PREPARE建议
将 master 的 3845c032 合回 2.7.3,改动仅为一个空格,可干净 cherry-pick。
日志
Source: 648540858/wvp-GB28181-pro