使用mybatisplus 做数据库兼容,以及对关键字的处理

最近公司有需求,需要对框架做oracle与mysql的兼容。由于框架以前一直是使用的oracle,现在需要做兼容,及是该框架同时支持oracle和mysql版本,oracle和mysql根据用户环境来选择,只需要切换数据库而不需要对代码做任何改动。

1. 自定义sql语句兼容。

    这个实际上是mybatis支持的,在mybatismapper.xml中,所有标签都支持databaseId属性,这个属性就是你选择的所属的数据库的ID, 而标签ID不在为唯一属性,需要和databaseId联合唯一。这个比较简单,只需要在spring里自定义DatabaseIdProvider就可以设置databaseId了

    /**
     * 数据库兼容,在mybatis里设置相应的databaseId即可
     */
    @Bean
    public DatabaseIdProvider databaseIdProvider(){
        DatabaseIdProvider databaseIdProvider=new VendorDatabaseIdProvider();
        Properties properties=new Properties();
        properties.setProperty("Oracle","oracle");
        properties.setProperty("MySQL","mysql");
        databaseIdProvider.setProperties(properties);
        return databaseIdProvider;
    }
<select id="getListCode" resultMap="codeMap" parameterType="java.lang.String" databaseId="oracle">
<select id="getListCode" resultMap="codeMap" parameterType="java.lang.String"  databaseId="mysql">

2. 使用Mybatisplus

因为mybatisplus的时候都是自动生成sql语句,我们无法去设置选择哪个databaseId,所以这里怎么处理呢,这个只需要在不同环境设置mybatis-plus.global-config.db-config.db-type = oracle/mysql  ,就可以了,我使用的配置中心来管理,分别做了一个oracle配置中心和mysql配置中心,当使用哪个时,只需要启动对应的配置中心就可以了,而应用不需要做任何改动。

但是使用mybatisplus时还有个注意的地方,当对某个列我们使用模糊查询时,@TableField(condition=SqlCondition.like),使用mysqlplus这个sqlcondition.like是针对mysql的,使用oracle时会报错,这里可以自定义一个兼容mysql和oracle的常量类

    public static final  String LIKE="%s LIKE CONCAT(CONCAT('%%',#{%s}),'%%')";

这个like就能同时兼容mysql和oracle了。

3. mysql关键字

迁移数据之后发现,我们在oracle使用过程中我们在某个表中使用到了key,value,这个字段在mysql中是关键字,直接查询会报错,需要做引号处理`key`,`value`这样才能使用。这种情况怎么处理呢,当然,如果不需要做兼容处理,这里很简单就能处理,

 @TableField(value = "`value`")
 private String value;

直接这样就可以了。

 但是我需要做兼容,这样肯定不行,mysql不会存在问题,但是使用oracle就会存在问题了,而annotation只能传入唯一静态常量。

1.然后研究源码,发现在TableFieldInfo中存在这样一段

String columnFormat = dbConfig.getColumnFormat();
        if (StringUtils.isNotEmpty(columnFormat)) {
            column = String.format(columnFormat, column);
        }

设置dbconfig,所以,我们可以在配置中心,mysql版本中设置mybatis-plus.global-config.db-config.columnFormat="`%s`"就可以了。

2.虽然有这种办法,但是这种会把所有mysql的列都会进行替换,那么还有没有其他的方式呢。

最终发现mysqlplus支持动态修改表名的一个接口  ITableNameHandler

public interface ITableNameHandler {
    default String process(MetaObject metaObject, String sql, String tableName) {
        String dynamicTableName = this.dynamicTableName(metaObject, sql, tableName);
        return null != dynamicTableName && !dynamicTableName.equalsIgnoreCase(tableName) ? sql.replaceAll(tableName, dynamicTableName) : sql;
    }

    String dynamicTableName(MetaObject metaObject, String sql, String tableName);
}

我就想,既然能动态修改表名,那肯定就能动态修改列名了,所以就可以这样做,

@Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setLimit(1000);

        //增加mysql的关键字处理
        String datatype=DataTypeConstant.getDataType();
        switch (datatype){
            case "mysql":
            {
                DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
                dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2) {{
                    put("CODE", new ITableNameHandler() {
                        @Override
                        public String dynamicTableName(MetaObject metaObject, String sql, String tableName) {
                            return null;
                        }
                        @Override
                        public String process(MetaObject metaObject, String sql, String tableName) {
                            if("CODE".equalsIgnoreCase(tableName)){
                                sql=sql.replaceAll("key","`key`");
                                sql=sql.replaceAll("value","`value`");
                            }
                            return sql;
                        }
                    });
                }});
                paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser));
            }
            break;
        }
        return paginationInterceptor;
    }

这样就可以了,如果还有其他数据库或者其他关键字,就可以直接在这里进行添加,在mybatisplus执行sql的时候,就会这里来进行替换掉关键字,然后在执行。

 

我这主要做兼容,导致才会有后面的问题。如果不需要做兼容, @TableField(value = "`value`")这样是最方便的。  

有什么问题疑问,可以来进行探讨。

发布了3 篇原创文章 · 获赞 0 · 访问量 239
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览