应用场景:之前架构大部分都是引入一种数据源进行数据的处理,而随着服务越多,生产场景和个性化的需要,在项目中使用mybatis兼容mysql与oracle已经成为了一个开发人员必备的知识储备,有助于在生产环境进行数据源mysql/oracle的切换。
这里将介绍一种简单而且适合小白快速上手的一种方案–databaseId数据库厂商标识。这个方案将分三步进行配置
第一步:引入数据源
这里我们可以通过yml文件引入datasource(数据源以mysql为例,如果要引入oracle在yml文件引入即可)
spring:
datasource:
url: jdbc:mysql://localhost:3306/xxx...
type: xxx
username: xxx
password: xxx
driver-class-name:xxx
第二步:配置@Bean
新建一个配置类进行注入@Bean(配置类记得加上@Configuration)–让项目知道走哪个databaseId
@Bean
public DatabaseIdProvider getDatabaseIdProvider() {
DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
Properties p = new Properties();
p.setProperty("Oracle", "oracle");
p.setProperty("MySQL", "mysql");
databaseIdProvider.setProperties(p);
return databaseIdProvider;
}
第三步:添加databaseId=“mysql”/"oracle"即可完成
在mapper中进行sql厂商标识的注入
<!--第一种:复制两个片段直接加上databaseId="mysql"/"oracle"-->
<select id="selectAllCoco" resultType="com.note.note.pojo.Coco" databaseId="mysql">
select id,name from cocodb;
</select>
<select id="selectAllCoco" resultType="com.note.note.pojo.Coco" databaseId="oracle">
select id,name from cocodb;
</select>
<!--第二种:引入if test = "mysql"/"oracle" databaseId="mysql"/"oracle" 进行改写-->
<insert id="insert">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
<if test="_databaseId == 'oracle'">
select seq_users.nextval from dual
</if>
<if test="_databaseId == 'db2'">
select nextval for seq_users from sysibm.sysdummy1"
</if>
</selectKey>
insert into users values (#{id}, #{name})
</insert>
源码解读:为什么加上DataSourceId=“mysql”/"oracle"就可以匹配对应的机制呢?
1.使用mybatis就需先创建sqlSessionFactory接口对象org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
内部包含org.apache.ibatis.session.Configuration属性,即mybatis-config配置文件信息,包括数据源、拦截器、插件、别名等
2.spring整合mybatis从SqlSession类型bean初始化进行解析时MyBatis根据数据库连接池获取到数据库厂商标识,然后按照映射关系过滤掉databaseId不匹配的statement语句,最后都放到org.apache.ibatis.session.Configuration#mappedStatements这个Map类型的属性当中
3.当业务请求的时候,调用xxMapper#selectAll接口的时候,只会映射到一个语句了。如果存在多个,首先根据databaseId匹配,然后在匹配没有databseId的,已经有匹配成功的则忽略。
扩展:oracle与mysql语句间的改写(mapper语句改写重点!!!)
1.oracle语法中的listagg语法–对应mysql的group_concat语法
--oracle--
listagg(label_id,',') WITHIN GROUP (ORDER BY audit_id) AS label_ids
--mysql--
group_concat(label_id order by audit_id ) as label_ids
2.oracle改造时间/to_char/trunc/nvl/add_month等函数**
--oracle--
nvl((sum(is_this_month) - sum(is_last_month)),0) as month_count
--mysql--
sum(ifnull(is_this_month,0)) - sum(ifnull(is_last_month,0)) month_count
--oracle--
to_char(TRUNC(add_months(trunc(sysdate), -1), 'MM'), 'MM') = to_char(VALID_DATE, 'MM')
then 1 else 0 end as is_last_month
--mysql--
Month(now() - 1) = Day(VALID_DATE) then 1 else 0 end is_last_month
--oracle--
when to_char(sysdate, 'MM') = to_char(VALID_DATE, 'MM')
--mysql--
Month(now()) = Month(VALID_DATE)
--oracle--
TRUNC(ADD_MONTHS(sysdate, -1), 'mm')
--mysql--
month(now()-1))