“动态 SQL 如何适配多数据库”通常出现在 MyBatis / MyBatis-Plus、JPA、Spring JDBC 等场景中。核心目标是:同一套 SQL 逻辑,在不同数据库(MySQL、Oracle、PostgreSQL、SQLServer…)上都能正确执行。
下面从 设计思路 → 常见方案 → 示例 三个层面说明。
适配多库要解决的差异主要有:
LIMIT vs ROWNUM vs OFFSET FETCHCONCAT / ||NOW() / SYSDATEIFNULL / NVL / COALESCE✅ 原则:动态 SQL 只描述“逻辑”,不写死数据库语法
databaseId(最推荐)MyBatis 原生支持多库识别。
mybatis:
configuration:
database-id: mysql
或 Java 配置:
@Bean
public DatabaseIdProvider databaseIdProvider() {
VendorDatabaseIdProvider provider = new VendorDatabaseIdProvider();
Map<String, String> map = new HashMap<>();
map.put("MySQL", "mysql");
map.put("Oracle", "oracle");
provider.setProperties(map);
return provider;
}
<select id="list" resultType="User">
<if test="_databaseId == 'mysql'">
SELECT * FROM user LIMIT #{offset}, #{size}
</if>
<if test="_databaseId == 'oracle'">
SELECT * FROM (
SELECT u.*, ROWNUM rn FROM user u
) WHERE rn BETWEEN #{offset}+1 AND #{offset}+#{size}
</if>
</select>
✅ 优点:清晰、官方支持
❌ 缺点:SQL 会变长
适合 复杂条件 + 多库逻辑
public String buildPageSql(String dbType) {
if ("mysql".equals(dbType)) {
return " LIMIT ?, ?";
} else if ("oracle".equals(dbType)) {
return " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
}
throw new UnsupportedOperationException();
}
用在:
@SelectProvider@Query + 自定义 RepositoryPaginationInnerInterceptor interceptor = new PaginationInnerInterceptor();
interceptor.setDbType(DbType.MYSQL);
自动处理:
spring:
jpa:
database-platform: org.hibernate.dialect.MySQL8Dialect
✅ 最省心
❌ 灵活性略低
适用于自研 ORM / 报表系统:
interface Dialect {
String pageSql(String sql, int offset, int size);
}
class MysqlDialect implements Dialect {
public String pageSql(String sql, int offset, int size) {
return sql + " LIMIT " + offset + "," + size;
}
}
| 功能 | MySQL | Oracle | PostgreSQL |
|---|---|---|---|
| 分页 | LIMIT | ROWNUM | OFFSET |
| 空值 | IFNULL | NVL | COALESCE |
| 当前时间 | NOW() | SYSDATE | CURRENT_TIMESTAMP |
| 自增 | AUTO_INCREMENT | SEQUENCE | SERIAL |
✅ 优先顺序
databaseId✅ 避免
if (dbType.equals("mysql"))如果你愿意,可以告诉我:
我可以直接给你可粘贴用的模板代码。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。