mybatis 通过 databaseidprovider + databaseid 机制实现多数据库适配,而非内置方言类;vendordatabaseidprovider 根据 jdbc 的 databaseproductname 映射 databaseid,xml 中按 databaseid 编写差异化 sql,无 databaseid 的为兜底语句;分页等通用差异推荐用 pagehelper 等插件统一处理;国产数据库可扩展映射或自定义 databaseidprovider。

MyBatis 本身不内置“dialect”配置项,也不直接提供 MySQLDialect、OracleDialect 这类开箱即用的方言实现类。它的多数据库适配能力,核心靠 DatabaseIdProvider + databaseId 机制驱动,配合 XML 中按 databaseId 分离 SQL 片段来实现——这是官方原生、轻量、稳定的方式。
databaseIdProvider:让 MyBatis “认出”当前数据库
MyBatis 通过 JDBC 的 DatabaseMetaData.getDatabaseProductName() 获取数据库厂商名(如 "MySQL"、"Oracle"、"PostgreSQL"),再根据你配置的映射表,生成一个简短的 databaseId(如 "mysql"、"oracle"、"postgresql")。这个 id 将作为后续 SQL 路由的关键标识。
最常用的是 VendorDatabaseIdProvider,配置示例如下:
注意:property 的 key 必须与 JDBC 返回的 product name 完全一致(区分大小写,空格也不能错),可通过日志或调试确认真实值。
XML 中按 databaseId 编写差异化 SQL
在 Mapper XML 文件中,同一个 <select></select> 可以定义多个版本,用 databaseId 属性区分。MyBatis 运行时自动选择匹配当前连接的版本:
未带 databaseId 的语句是兜底版本,所有数据库都可执行;带 databaseId 的语句只在对应数据库下生效。优先级:精确匹配 > 无 databaseId。
分页等通用差异,推荐用插件统一处理
手写多套分页 SQL 易出错、难维护。主流做法是引入 PageHelper 或自研分页插件,它们内部已封装各数据库的分页逻辑:
- MySQL / PostgreSQL:用
LIMIT ? OFFSET ? - Oracle 12c+:用
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY - SQL Server:用
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY或TOP - 旧版 Oracle:三层 ROWNUM 嵌套
启用 PageHelper 后,你只需写标准 SQL,调用 PageHelper.startPage(pageNum, pageSize),插件会自动拦截并重写为对应方言的分页语句。
自定义方言扩展:当 vendor provider 不够用时
如果遇到 GaussDB、达梦、人大金仓等国产库,其 getDatabaseProductName() 返回值不在默认映射中(比如返回 "Zenith" 或 "DM Database"),你需要:
- 在
VendorDatabaseIdProvider的 properties 中补充映射,如<property name="Zenith" value="gaussdb"></property> - 或实现自己的
DatabaseIdProvider子类,覆盖getDatabaseId(Connection)方法,做更灵活的识别(比如解析 URL、检查驱动类名) - 若需深度定制 SQL 生成逻辑(如函数替换、类型转换),可开发 MyBatis Interceptor 插件,在 StatementHandler 层动态改写 SQL
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











