MyBatis之databaseIdProvider多数据库支持
一、databaseIdProvider官方描述MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 这里什么意思呢
一、databaseIdProvider官方描述
MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。
这里什么意思呢 ,如果你仔细看过mybatis的官方文档中关于XML映射文件章节中的 select
<select
id="selectPerson"
parameterType="int"
parameterMap="deprecated"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10000"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">
下面的解释中有一个databaseId属性: 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。新增,修改和删除都有这个属性。例如mysql的获取系统时间函数 NOW() 和oracle的获取系统时间to_char(sysdate,’yyyy-mm-dd hh24:mi:ss’) 是不同的。那么我们可以针对同一个修改可以写两个update语句,他们的databaseId属性不一样。
再比如数据库数据分页见MyBatis 入门(六)–分页查询(1)和MyBatis 入门(六)–分页查询(2) -插件方式他们的语句就是不一样,就可以利用这种模式获取当前数据,再做不同的处理。
为支持多厂商特性只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider 即可:
- 配置
<databaseIdProvider type="DB_VENDOR" />
这里的 DB_VENDOR 会通过 DatabaseMetaData#getDatabaseProductName() 返回的字符串进行设置 见JDBC-基础。 由于通常情况下这个字符串都非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短,如下:
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle" />
</databaseIdProvider>
在有 properties 时,DB_VENDOR databaseIdProvider 的将被设置为第一个能匹配数据库产品名称的属性键对应的值,如果没有匹配的属性将会设置为 “null”。 在这个例子中,如果 getDatabaseProductName() 返回“Oracle (DataDirect)”,databaseId 将被设置为“oracle”。
你可以通过实现接口 org.apache.ibatis.mapping.DatabaseIdProvider 并在 mybatis-config.xml 中注册来构建自己的 DatabaseIdProvider:
public interface DatabaseIdProvider {
void setProperties(Properties p);
String getDatabaseId(DataSource dataSource) throws SQLException;
}
应用时可以直接通过Configuration的getDatabaseId方法来获取当前数据的供应商。
二、mysql和oracle两种数据库的应用实例
在这里我们就实现mysql的获取系统时间函数 NOW() 和oracle的获取系统时间to_char(sysdate,’yyyy-mm-dd hh24:mi:ss’) 的的执行。
- 首先配置 mybatis-config.xml
<properties resource="jdbc.properties" />
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql" />
<property name="Oracle" value="oracle" />
</databaseIdProvider>
<mappers>
<mapper class="com.elements.user.dao.dbMapper" />
</mappers>
- 接口和mapperXML文件
package com.elements.user.dao;
public interface dbMapper {
String SelectTime();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.elements.user.dao.dbMapper" >
<select id="SelectTime" resultType="String" databaseId="mysql">
SELECT NOW() FROM dual
</select>
<select id="SelectTime" resultType="String" databaseId="oracle">
SELECT 'oralce'||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') FROM dual
</select>
</mapper>
上面的mapper文件具有相同的id,但是他们的databaseId分别是mysql和oralce。
- jdbc.properties文件
#driver=com.mysql.cj.jdbc.Driver
#url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&useSSL=true&serverTimezone=UTC
#username=mybatis
#password=mybatis
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:mybatis
username=mybatis
password=mybatis
maxActive= 50
这个配置文件以及注销了mysql的链接,启用的是oralce的链接
- 测试类
package com.elements.user;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import com.elements.user.dao.dbMapper;
public class TestDB {
@Test
public void Testdb() throws IOException
{
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
dbMapper user = (dbMapper) session
.getMapper(dbMapper.class);
System.out.println(user.SelectTime());
} finally {
session.close();
}
}
}
- 结果说明
如果当前启用的是oracle则执行databaseId=”oracle”的语句,如果mysql值执行databaseId=”mysql”的语句
如果又遇到配置文件添加报错的,可以尝试第二种方法:
这里要用到mybatis的databaseId。如下:
<select id="isExist" resultType="Boolean" databaseId="mysql">
SELECT EXISTS(SELECT 1 FROM `${db}`.test_table WHERE table_id=#{tableId} LIMIT 1)
</select>
<select id="isExist" resultType="Boolean" databaseId="oracle">
SELECT COUNT(*) FROM ${db}."test_table " WHERE "table_id"=#{tableId}
</select>
在mapper.xml中加上databaseId就可以指定要用的sql,mybatis会根据链接过来的DataSource自动识别。
我这里使用的是spring boot,加上一个bean的配置:
/**
* 自动识别使用的数据库类型
* 在mapper.xml中databaseId的值就是跟这里对应,
* 如果没有databaseId选择则说明该sql适用所有数据库
* */
@Bean
public DatabaseIdProvider getDatabaseIdProvider(){
DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
Properties properties = new Properties();
properties.setProperty("Oracle","oracle");
properties.setProperty("MySQL","mysql");
properties.setProperty("DB2","db2");
properties.setProperty("Derby","derby");
properties.setProperty("H2","h2");
properties.setProperty("HSQL","hsql");
properties.setProperty("Informix","informix");
properties.setProperty("MS-SQL","ms-sql");
properties.setProperty("PostgreSQL","postgresql");
properties.setProperty("Sybase","sybase");
properties.setProperty("Hana","hana");
databaseIdProvider.setProperties(properties);
return databaseIdProvider;
}
我这里列出了所有支持的数据库类型,实际使用的时候根据自己要用的数据库添加就好。
在配置文件中正常配置数据库信息就可以了。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)