插件窝 干货文章 如何使用 Mybatis 数据库厂商标识执行动态 SQL?

如何使用 Mybatis 数据库厂商标识执行动态 SQL?

select databaseId 数据库 WHERE 864    来源:    2025-03-30

MyBatis 数据库厂商标识执行动态 SQL

MyBatis 提供了基于数据库厂商标识(DatabaseIdProvider)来执行不同数据库的动态 SQL 功能,这对于需要支持多数据库的应用非常有用。

基本配置

首先需要在 MyBatis 配置文件中配置数据库厂商标识:

<databaseIdProvider type="DB_VENDOR">
    <property name="MySQL" value="mysql"/>
    <property name="Oracle" value="oracle"/>
    <property name="PostgreSQL" value="postgresql"/>
    <property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>

在映射文件中使用

在 XML 映射文件中,可以使用 databaseId 属性来指定特定数据库的 SQL:

<select id="findUser" resultType="User">
    <if test="_databaseId == 'mysql'">
        SELECT * FROM users WHERE id = #{id}
    </if>
    <if test="_databaseId == 'oracle'">
        SELECT * FROM users WHERE ROWID = #{id}
    </if>
</select>

或者更简洁的方式:

<select id="findUser" resultType="User" databaseId="mysql">
    SELECT * FROM users WHERE id = #{id}
</select>

<select id="findUser" resultType="User" databaseId="oracle">
    SELECT * FROM users WHERE ROWID = #{id}
</select>

动态 SQL 中的使用

在动态 SQL 中,可以通过 _databaseId 变量来判断当前数据库:

<select id="findUsers" resultType="User">
    SELECT * FROM users
    <where>
        <if test="name != null">
            AND name like #{name}
        </if>
        <if test="_databaseId == 'oracle'">
            AND ROWNUM &lt;= 10
        </if>
        <if test="_databaseId == 'mysql'">
            LIMIT 10
        </if>
    </where>
</select>

注解方式使用

在注解方式中,可以使用 @SelectProvider 配合自定义的 SQL 提供类来实现:

public class UserSqlProvider {
    public String findUser(Map<String, Object> params) {
        String dbId = (String) params.get("_databaseId");
        if ("mysql".equals(dbId)) {
            return "SELECT * FROM users WHERE id = #{id}";
        } else if ("oracle".equals(dbId)) {
            return "SELECT * FROM users WHERE ROWID = #{id}";
        }
        return "SELECT * FROM users WHERE id = #{id}";
    }
}

@SelectProvider(type = UserSqlProvider.class, method = "findUser")
User findUserById(Long id);

最佳实践

  1. 默认 SQL:总是提供一个不带 databaseId 的默认 SQL 语句
  2. 测试覆盖:确保为所有支持的数据库测试 SQL 语句
  3. 版本差异:考虑同一数据库不同版本间的 SQL 差异
  4. 性能考虑:避免过于复杂的动态 SQL,可能影响解析性能

通过合理使用数据库厂商标识,可以轻松实现多数据库支持,同时保持代码的整洁和可维护性。