[BUG] 2.7.3 分支 DeviceMapper.update 的 SQL 缺少空格,库中存在在线设备时启动必失败

Author: zhw5592Created Sep 18, 2026Updated Sep 18, 2026

环境信息:

    1. 部署方式 wvp-pro docker(Dockerfile 内 git clone 后 checkout 2.7.3 自行编译)
    1. 部署环境 ubuntu (docker)
    1. 端口开放情况 3000 / 5060(tcp+udp),host 网络
    1. 是否是公网部署 是
    1. 是否使用https 否
    1. 接入设备/平台品牌 GB28181 摄像机
    1. 你做过哪些尝试 已定位到 SQL 渲染结果,并与 master 对比确认该问题在 master 已修复
    1. 代码更新时间 2.7.3 分支 b1ff1ef(2025-05-26)
    1. 是否是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 默认处理器吞掉, 表现为设备在线状态静默不再刷新。

如何复现

  1. 用 2.7.3 分支编译部署,数据库使用 PostgreSQL
  2. 让任意一台国标设备注册成功(首次注册走 deviceMapper.add,SQL 正常,库中写入 on_line=true
  3. 重启 wvp
  4. 启动即失败

也可直接在 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