在“动态 SQL 做缓存”这个问题上,需要先明确一点:缓存的对象通常不是“SQL 字符串本身”,而是“SQL 执行结果”或“解析后的 SQL 结构”。下面按常见场景系统讲一下。
动态 SQL 一般指:
<if>、<foreach>)这类 SQL 不易被传统 SQL 缓存命中,因为:
适合:复杂动态 SQL 拼接代价大
做法:
示例(伪代码):
String sql = sqlCache.get(conditionKey);
if (sql == null) {
sql = buildDynamicSql(condition);
sqlCache.put(conditionKey, sql);
}
✅ 优点:减少字符串拼接 / 解析
❌ 不解决数据一致性问题
适合:读多写少、数据变化不频繁
<cache/>
注意:
String cacheKey = buildKey(sql, params);
Object data = redis.get(cacheKey);
if (data == null) {
data = mapper.query(params);
redis.set(cacheKey, data, 5min);
}
✅ 命中率高
✅ 可控
❌ 需处理失效
数据库层天然支持:
? 占位符✅ 动态 SQL 应尽量:
WHERE name = ? AND age = ?
而不是:
WHERE name = 'tom' AND age = 18
必须包含:
key = md5(sql + params + page + tenant)
常见方案:
@CacheEvict(value="user", key="#user.id")
❌ 实时性要求高
❌ 数据频繁变化
❌ 结果集很大
❌ 权限敏感(不同人结果不同)
✅ 动态 SQL 优先缓存结果,而不是 SQL 本身
✅ 用参数化 SQL 提升数据库缓存效率
✅ 手动 Cache(Redis / Caffeine)比框架 Cache 更可控
✅ Key 设计必须“完全决定结果”
如果你用的是 MyBatis / MyBatis-Plus / JPA / 原生 JDBC,我可以给你具体实现示例。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。