应查清数据库中update_by字段实际长度,如varchar(20),并在业务层主动截断而非依赖异常;需同步更新orm映射、前端校验及接口层限制,避免问题延迟爆发。

查清 update_by 字段实际定义长度
直接连数据库执行:DESC sys_notice; 或 SHOW CREATE TABLE sys_notice;,重点看 update_by 的类型和长度,比如 VARCHAR(20)。别信 ORM 实体类里的注解或 Lombok 生成的 getter —— 它们不决定数据库行为,只反映开发时的假设。如果字段用的是 utf8mb4 字符集,20 个字符最多占 80 字节(每个中文 4 字节),但 MySQL 校验长度是按字符数,不是字节数;所以真正瓶颈是字符长度本身。
updateNoticeAndDetail 方法里必须做截断而非抛异常
Spring 的 DataIntegrityViolationException 是事后补救,不该是常态。在业务方法里主动控制输入更可靠:
- 从上游(如
SecurityContextHolder或 JWT token)拿到的用户名/登录名,可能含长邮箱、UUID 或带域前缀的 AD 账号,长度不可控 - 不要用
substring(0, 20)硬切 —— 中文可能被截半导致乱码,优先用StringUtils.substring(updateBy, 0, maxLength)(Apache Commons),它按 Unicode 字符切,安全 - 截断后建议打一条 warn 日志,包含原始值哈希(如
MD5(updateBy).substring(0,8))和截断提示,方便后续追查谁在传超长值
JOIN 或视图嵌套时 update_by 参与关联会静默失效
如果报表或权限校验逻辑里写了类似 ON n.update_by = u.username,而 u.username 来自一个嵌套视图,且该视图里没显式 CAST(username AS VARCHAR(64)),SQL Server 或达梦可能把它推导成 VARCHAR(30) 甚至 VARCHAR(0),导致关联失败但不报错——数据漏了你还不知道。
验证方式:对涉及视图执行 SELECT TOP 0 * FROM your_view,再查 sys.dm_exec_describe_first_result_set 看 max_length 列。修复就是在外层视图里统一加 CAST(update_by AS VARCHAR(100)),长度取数据库字段定义值,别凭感觉写。
改表结构前先确认约束和依赖
ALTER TABLE sys_notice MODIFY COLUMN update_by VARCHAR(100); 在 MySQL 里可能失败,因为字段上有外键、索引或触发器依赖。SQL Server 更麻烦,常卡在“对象依赖”上:
- 先跑
SELECT name FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID('sys_notice');找外键 - 用
sp_helpconstraint 'sys_notice'查 CHECK 或 DEFAULT 约束 - 删约束不是目的,是为改字段铺路;删完立刻重建,避免线上缺失约束逻辑
- 改完字段长度,别忘了同步更新 MyBatis 的
resultMap或 JPA 的@Column(length = 100),否则 Hibernate 还会按旧长度预编译 SQL
最易被忽略的点:字段扩到 VARCHAR(100) 后,如果上游系统仍传 200 字符的值,问题只是延迟爆发——得配合前端 maxlength="100" 和接口层校验双保险,否则治标不治本。











