mybatis plus 插入有唯一索引报错 时进行更新操作,这样避免报错

24 阅读2分钟
INSERT INTO aaa (project_id, reasona, subreasona, problem_statusa) 
VALUES (#{entity.projectIda}, #{entity.reasona}, #{entity.subreasona}, #{entity.problemStatusa}) 
ON DUPLICATE KEY UPDATE 
problem_statusa = IF(problem_statusa IN (1, 11, 14), VALUES(problem_statusa), IF(CAST(fixed_versiona AS UNSIGNED) >= CAST(#{entity.fixedVersiona} AS UNSIGNED), VALUES(problem_statusa), 14));

各部分含义

1. 插入部分

  • INSERT INTO aaa (...) VALUES (...):尝试向aaa表插入一条新记录,包含project_idreasonsubreasonproblem_status四个字段。
  • #{entity.xxx}是参数占位符(可能是MyBatis等ORM框架的语法),表示从实体对象中获取对应属性值。

2. ON DUPLICATE KEY UPDATE 部分(重点)

这是MySQL的扩展语法,用于处理插入冲突:

  • 当插入操作遇到主键或唯一索引冲突(即表中已存在相同主键或唯一索引的记录)时,不会报错,而是执行后续的UPDATE操作。
  • problem_status = ...:指定冲突时要更新的字段及其值。

3. 更新逻辑解析

更新problem_status字段的逻辑使用了嵌套的IF函数,分两层判断:

第一层判断IF(problem_status IN (0, 2, 4), VALUES(problem_status), ...)

  • 如果现有记录的problem_status值在(0, 2, 4)这个集合中,则更新为新插入的值(VALUES(problem_status)表示使用插入语句中problem_status字段的值)。
  • 否则,进入第二层判断。

第二层判断IF(CAST(fixed_version AS UNSIGNED) >= CAST(#{entity.fixedVersion} AS UNSIGNED), VALUES(problem_status), 4)

  • 这层判断比较现有记录的fixed_version和新值的大小(都转换为无符号整数进行比较)。
  • 如果现有版本大于等于新版本,则更新为新插入的problem_status值。
  • 否则,将problem_status设置为固定值4

核心作用

这个SQL实现了一种"智能"的插入/更新策略,既能避免主键冲突错误,又能根据记录的当前状态和版本信息来决定是否更新以及如何更新状态字段。常用于需要保持数据最新状态,同时又要考虑版本兼容性的场景。