小工具 · 规范库 · 后端代码规范(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-starter1.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),不要靠"手动在库上改",并保证可重入。
- 兼容存量数据:加字段给默认值,删字段先停用。