宇我的小宇宙
小工具 · 规范库 · 后端代码规范(Java / Spring Boot / SQL)

SQL 与 MyBatis 规范

← 返回上一页
rules/10-backend/sql-and-mybatis.md

SQL 与 MyBatis 规范

数据库基线(HisParent/pom.xml)

  • 主数据库:Oracle(oracle.jdbc.driver.OracleDriver,jdbc:oracle:thin:@<DB_HOST>:1521/his)
  • 同时保留 MariaDB / MSSQL 驱动支持(多机构/多库场景),但默认按 Oracle 语法编写。
  • 连接池:Druid(druid-spring-boot-starter 1.1.10)。
安全提示:真实连接信息见 00-global/security-anti-leak.md,禁止写入示例/提交。

SQL 编写

方言

  • 默认 Oracle 语法:
  • 分页用 ROWNUM 或 OFFSET ... FETCH(视 Oracle 版本)。
  • 字符串拼接 ||、NVL() 处理空、SYSDATE 取当前时间、序列 seq_xxx.NEXTVAL。
  • 日期处理用 TO_DATE / TO_CHAR。
  • 仅当明确面向 MariaDB/MSSQL 的模块,才切换对应方言。

注入防护(强制)

  • MyBatis 参数一律用 #{param}(预编译占位符)。
  • 禁止用 ${param} 拼接用户可控输入(SQL 注入)。
  • ${} 仅允许用于不可变的 SQL 结构(如表名/列名/排序方向,且必须来自白名单校验),并在注释中标注为何安全。

<select id="findByName" resultType="RegPO">
    SELECT * FROM T_REG WHERE NAME = #{name}
</select>


<select id="findByName" resultType="RegPO">
    SELECT * FROM T_REG WHERE NAME = '${name}'   
</select>

性能与正确性

  • 避免 SELECT *,显式列出字段(性能、字段变更影响可控)。
  • WHERE 条件字段走索引;避免对索引列做函数包裹导致失效(如 WHERE TO_CHAR(date,'yyyyMMdd')='20240101' 改为范围查询)。
  • 批量操作用 IN 或批处理,禁止在 Service 循环里逐条 SQL(N+1)。
  • UPDATE/DELETE 必须带 WHERE,防止全表误操作。

MyBatis 映射

  • SQL 写在 XML 映射文件中(与现有代码一致),复杂 SQL 不写在注解里。
  • <resultMap> 显式映射,避免靠字段名自动映射导致的隐性错位。
  • 动态 SQL 用 <if>/<choose>/<foreach>,注意 WHERE 关键字防多余 AND(用 <where> 或 1=1 既有约定)。
  • #{} 与实体属性对应;<foreach> 的 collection、item、separator 齐全。

事务与一致性

  • 写操作(INSERT/UPDATE/DELETE)应在 Service 事务内(见 spring-boot-service.md)。
  • 涉及号源、库存、金额的字段更新,用乐观锁(version 字段)或 WHERE 条件带状态判断,避免超卖。

命名

  • 表名:模块前缀 + 大写下划线,如 T_REG_REGISTER、T_CHG_BILL(遵循模块既有命名)。
  • 字段:大写下划线 CREATE_TIME、ORG_CODE。

迁移

  • 表结构/数据变更通过迁移脚本(DDL/DML),不要靠"手动在库上改",并保证可重入。
  • 兼容存量数据:加字段给默认值,删字段先停用。