当前位置: 首页 > 知识库问答 >
问题:

MyBatis对多数据库的支持

端木野
2023-03-14

我有不同的客户使用不同的数据库服务器(postgres,oracle,mysql等)

我想写我的代码一次,并能够在不同的数据库运行。

实现这一点的“Mybatis”方法是什么?

    null

我正在使用mybatis java注释。

共有1个答案

云新知
2023-03-14

您说您在使用注释,但我建议使用XML。我通常发现它更清晰,尤其是因为无论如何都需要完全更改查询的某些部分。

下面是一个DDL示例,在该示例中,为相同的方法获得两个独立的XML元素,但数据库ID不同。这些表非常相似,但是由于检查表是否已经存在的方式以及类型的本质不同,因此不能避免使用不同的SQL代码:

<update id="createTables" databaseId="postgresql">
    DO $$
    BEGIN
        CREATE TABLE IF NOT EXISTS item (
            id SERIAL PRIMARY KEY,
            content TEXT,
            creation_datetime TIMESTAMPTZ DEFAULT NOW(),
            modification_datetime TIMESTAMPTZ
        );
    END$$
</update>
<update id="createTables" databaseId="sqlserver">
    IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'item')
    BEGIN
        CREATE TABLE item (
            id INT IDENTITY PRIMARY KEY,
            content NVARCHAR(MAX),
            creation_datetime DATETIMEOFFSET DEFAULT SYSDATETIMEOFFSET(),
            modification_datetime DATETIMEOFFSET
        );
    END
</update>

您也可以在SQL元素中设置查询,但根据数据库ID,使用 (或 )更改不同的部分。如果变化很小,这很好:

<delete id="deleteItem">
    DELETE FROM my_item
    WHERE gid=CAST(#{gid} AS <if test="_databaseId == 'postgresql'">UUID</if><if test="_databaseId == 'sqlserver'">UNIQUEIDENTIFIER</if>)
</delete>

<select id="getLatestSomething" resultType="test.Something">
    SELECT <if test="_databaseId == 'sqlserver'">TOP 1</if> *
    FROM something
    ORDER BY creation_datetime DESC
    <if test="_databaseId == 'postgresql'">
    LIMIT 1
    </if>
</select>
<insert id="insertStuff" parameterType="somestuff.Stuff">
    <if test="_databaseId == 'postgresql'">
        INSERT INTO my_stuff (...)
    </if>
    <if test="_databaseId == 'sqlserver'">
        MERGE INTO my_stuff WITH (HOLDLOCK) AS t USING (
    </if>
            VALUES (#{...},
                    <if test="_databaseId == 'postgresql'">
                        CAST(#{jsonData} AS JSONB)
                    </if>
                    <if test="_databaseId == 'sqlserver'">
                        #{jsonData}
                    </if>
            )
    <if test="_databaseId == 'postgresql'">
            ON CONFLICT DO NOTHING
    </if>
    <if test="_databaseId == 'sqlserver'">
        )
              AS s (...)
              ON t....=s....
                 AND t....=s....
        WHEN NOT MATCHED BY TARGET THEN
            INSERT (...)
            VALUES (s...., s....);
    </if>
</insert>

在MyBatis Dynamic SQL文档中有更多关于这一切的内容。

假设XML映射器文件位于myPackage/myMapper.XML中,则可以在匹配该目录的包中使用myMapperJava接口。那里没有特定于数据库ID的东西。

package mypackage;

public interface MyMapper {
    void createTables();
    void deleteItem(@Param("gid") UUID gid);
    Something getLatestSomething();
}

在Spring中使用MyBatis时,可以如下设置供应商配置:

@Bean
public VendorDatabaseIdProvider vendorDatabaseIdProvider() {
    Properties vendorProperties = new Properties();
    vendorProperties.setProperty("PostgreSQL", "postgresql");
    vendorProperties.setProperty("SQL Server", "sqlserver");
    // Add others as required, this will look for the substring in the product name coming
    // from the database metadata.

    // ...
    VendorDatabaseIdProvider dbIdProvider = new VendorDatabaseIdProvider();
    dbIdProvider.setProperties(vendorProperties);
    return dbIdProvider;
}

@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource, ApplicationContext appContext,
        VendorDatabaseIdProvider vendorDatabaseIdProvider) throws Exception {
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setDatabaseIdProvider(vendorDatabaseIdProvider);

    SqlSessionFactory factory = bean.getObject();
    return factory;
}
String databaseId = databaseIdProvider.getDatabaseId(dataSource);
configuration.setDatabaseId(databaseId);

(如果您查看org.apache.ibatis.mapping.vendordatabaseIDProvider的代码,您将看到databaseidProvider.getdatabaseID(...)只是在databaseMetadata.getdatabaseProductName()返回的内容中寻找匹配的子字符串。如果需要,您也可以通过其他设置手动完成此操作。)

请注意,当databaseid=“”直接用作XML元素的属性时,没有下划线,但是当它用作测试条件时,它被称为_databaseid

 类似资料:
  • 1. 前言 动态 SQL 是 MyBatis 最标志性的特性之一。在其它框架中,你可能需要根据不同的条件来拼接 SQL,辗转在符号与条件的判断上,处理起来麻烦而且易错,而 MyBatis 的动态 SQL 可以让我们摆脱这种痛苦,简单而又高效的书写 SQL。 MyBatis 动态 SQL 由 OGNL 表达式和条件标签两部 分组成,我们将会分为多个小节进行介绍。 OGNL 表达式是动态 SQL 的基

  • 目前ActiveRecordPlugin提供了MysqlDialect、OracleDialect、PostgresqlDialect、SqlServerDialect、Sqlite3Dialect、AnsiSqlDialect实现类。MysqlDialect与OracleDialect分别实现对Mysql与Oracle的支持,AnsiSqlDialect实现对遵守ANSI SQL数据库的支持。以

  • Django试图尽可能多的支持所有数据库后端的特性。然而,并不是所有数据库都一样,所以我们必须在支持哪些特性和做出哪些安全的假定上做出设计决策。 本文描述了一些Django使用数据库的有关特性。当然,它并不想成为各服务器指定的文档或者参考手册的替代品。 综合说明 持续连接特性 持续连接的特性避免了每一次重新建立与数据库的连接的请求中所增加的压力。这些连接通过 CONN_MAX_AGE 参数(控制一

  • 问题内容: 我们在项目中使用MYSQL和Hibernate。 JPA用于将对象持久存储在DB中。 我们有多个具有相似代码的类 现在我们也想对oracle提供支持。我们应该怎么做?oracle不支持strategy = GenerationType.AUTO。 一个解决方案是我们可以在每个POJO中定义我们不想做的序列吗? 请提供一些建议,以便我们继续前进。 问题答案: AUTO策略也应适用于Ora

  • 问题内容: 在像mySQL这样的RDBMS数据库中处理多对多关系的最佳方法是什么? 尝试使用数据透视表来跟踪关系,但这会导致以下任一情况: 规范化被抛在后面 空或空的列 您采取了什么方法来支持多对多关系? 问题答案: 在 专门针对该关系 的 表 (有时称为 联结表 )中跟踪多对多关系。该表将该关系建模为指向相反方向的两个一对多关系。 然后,您可以使用联结表通过外键 通过它 联接 其他表 。

  • 1.16.1. 什么是 PyMySQL? PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。 PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。 1.16.2. PyMySQL安装 PyMySQL下载地址:https://github.com/PyMy