Oracle MyBatis支持多个数据库

Oracle MyBatis支持多个数据库,oracle,postgresql,mybatis,ibatis,Oracle,Postgresql,Mybatis,Ibatis,我有不同的客户使用不同的数据库供应商(postgres、oracle、mysql等) 我想写我的代码一次,并能够运行在不同的数据库 实现这一目标的“mybatis”方式是什么 到目前为止我发现的问题,例如: postgres在CREATESQL语句中有“如果不存在”的概念。oracle不支持这一点 oracle在sql语法中没有“限制”和“偏移”支持,而其他db则有 DDL语句中的文本(postgres)与clob(oracle和其他)jdbc类型 我不想重复我的查询(到目前为止我就是这么做

我有不同的客户使用不同的数据库供应商(postgres、oracle、mysql等)

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

实现这一目标的“mybatis”方式是什么

到目前为止我发现的问题,例如:

  • postgres在CREATESQL语句中有“如果不存在”的概念。oracle不支持这一点
  • oracle在sql语法中没有“限制”和“偏移”支持,而其他db则有
  • DDL语句中的文本(postgres)与clob(oracle和其他)jdbc类型
我不想重复我的查询(到目前为止我就是这么做的)。也许有一种更优雅的方式来做这件事


我使用的是mybatis java注释。

您是说您使用的是注释,但我建议使用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>
将MyBatis与Spring一起使用时,可以如下设置供应商配置:

@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;
}
如果未使用Spring,则应该能够使用配置数据库提供程序

您不需要严格的数据库ID提供程序。它所做的只是根据从
数据源
获取的产品名称,在配置中设置数据库ID。大致如下:

String databaseId = databaseIdProvider.getDatabaseId(dataSource);
configuration.setDatabaseId(databaseId);
(如果您查看
org.apache.ibatis.mapping.VendorDatabaseIdProvider
,您会发现
databaseIdProvider.getDatabaseId(…)
只是在从
DatabaseMetaData.getDatabaseProductName()
返回的内容中查找匹配的子字符串。如果需要,您也可以通过其他设置手动执行此操作。)


请注意,当直接将
databaseId=“
用作XML元素的属性时,没有下划线,但当将其用作测试条件时,称为
\u databaseId

谢谢@Bruno。我基本上将查询定义为输入到映射器界面上的Select、Delete等注释中的Constands。那么-您是说必须使用不同的sql语句?您能否共享将使用哪个Java api来加载每个DB提供程序的“createTables”?我对此不熟悉approach@YaOg我不确定是否有办法定制语句,因为MyBatis允许您编写将发送到RDBMS的SQL,这与ORM或其他中间层不同。控制SQL是MyBatis的一项功能,但缺点是您必须编写SQL,以便您所使用的特定RDBMS能够理解。通常,您可以在同一个查询中进行简单的测试,但有时供应商之间的语法差异太大。
package mypackage;

public interface MyMapper {
    void createTables();
    void deleteItem(@Param("gid") UUID gid);
    Something getLatestSomething();
}
@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);