4.6 多数据库支持
bind标签并不能解决更换数据库带来的所有问题,那么还可以通过什么方式支持不同的数据库呢?这需要用到if 标签以及由MyBatis提供的databaseIdProvider数据库厂商标识配置。
MyBatis可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的databaseId属性的。
MyBatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句。
如果同时找到带有databaseId和不带databaseId的相同语句,则后者会被舍弃。
为支持多厂商特性,只要像下面这样加入databaseIdProvider配置即可。
private static final Properties DB_VENDOR = new Properties();
static {
DB_VENDOR.put("SQL Server", "sqlserver");
DB_VENDOR.put("DB2", "db2");
DB_VENDOR.put("Oracle", "oracle");
DB_VENDOR.put("MySQL", "mysql");
DB_VENDOR.put("PostgreSQL", "postgresql");
DB_VENDOR.put("Derby", "derby");
DB_VENDOR.put("HSQL", "hsqldb");
DB_VENDOR.put("H2", "h2");
}
VendorDatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
databaseIdProvider.setProperties(DB_VENDOR);
sqlSessionFactoryBean.setDatabaseIdProvider(databaseIdProvider);
上面列举了常见的数据库产品名称,在存在匹配项时,databaseId将被设置为第一个能匹配数据库产品名称的属性键对应的值,如果没有匹配的属性则会被设置为null。在这个例子中,如果getDatabaseProductName()返回Microsoft SQL Server,databaseId将被设置为sqlserver。
DB_VENDOR的匹配策略为部分匹配(使用String.contains方法进行判断),所以虽然SQL Server的产品全名一般为Microsoft SQL Server,但这里只要设置为SQL Server就可以匹配。
数据库产品名一般由所选择的当前数据库的JDBC驱动所决定(DatabaseMetaData从connection对象中获取),只要找到对应数据库DatabaseMetaData接口的实现类,一般在getDatabaseProductName()方法中就可以直接找到该值。任何情况下都可以通过调用DatabaseMetaData#getDatabaseProductName()方法获取具体的值。
除了增加上面的配置外,映射文件也是要变化的,关键在于以下几个映射文件的标签中含有的databaseId属性:select、insert、delete、update、selectKey、sql。
<select id="selectByName" resultMap="BaseResultMap" databaseId="mysql">
select
ID, `NAME`, CODE
from country
where
`NAME` like = concat('%', #{name}, '%')
</select>
<select id="selectByName" resultMap="BaseResultMap" databaseId="oracle">
select
ID, `NAME`, CODE
from country
where
`NAME` like = '%'||#{name}||'%'
</select>
当基于不同数据库运行时,MyBatis会根据配置找到合适的SQL去执行。
数据库的更换可能只会引起某个SQL语句的部分不同,所以也没有必要使用上面的写法,而可以使用 if 标签配合默认的上下文中的_databaseId参数这种写法去实现。这样可以避免大量重复的SQL出现,方便修改。
<select id="selectByName" resultMap="BaseResultMap" databaseId="oracle">
select
ID, `NAME`, CODE
from country
<where>
<if test="_databaseId == 'mysql'">
`NAME` like = concat('%', #{name}, '%')
</if>
<if test="_databaseId == 'oracle'">
`NAME` like = '%'||#{name}||'%'
</if>
</where>
</select>
Last updated