Oracle MyBatis支持多个数据库
我有不同的客户使用不同的数据库供应商(postgres、oracle、mysql等) 我想写我的代码一次,并能够运行在不同的数据库 实现这一目标的“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在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);