springboot适配mybatis+guassdb与Mysql兼容性问题处理

我们在做一些兼容非MySQL数据库时,经常遇到一些关键字,或者语法差异问题。 这里举个极端例子,有个字段为desc,因为与数据库关键字冲突,在mysql中需要使用`desc`,而guassdb中需要使用"desc"

针对有语法差异的,利用mybatis的@Intercepts注解插件拦截,在拦截器中,处理与mysql的兼容性问题,通过类型判断,写不同逻辑

java 复制代码
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Properties;


@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}))
public class SqlDialectInterceptor implements Interceptor {

    private String databaseType;

    public SqlDialectInterceptor(String databaseType) {
        this.databaseType = databaseType;
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        String adjustedSql = adjustedSql(sql);
        Field sqlField = boundSql.getClass().getDeclaredField("sql");
        sqlField.setAccessible(true);
        sqlField.set(boundSql, adjustedSql);
        return invocation.proceed();
    }

    private String adjustedSql(String sql) {
        if (databaseType.toLowerCase().contains("mysql")) {
            sql = sql.replace("\"desc\"", "`desc`");
        } else {
            sql = sql.replace("`desc`", "\"desc\"");
        }
        return sql;
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
java 复制代码
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;


@Configuration
@MapperScan(basePackages = "com.db.mapper")
public class SqlSessionFactoryConfig {

    private static final Logger loggder = LoggerFactory.getLogger(SqlSessionFactoryConfig.class);

    private final DataSource dataSource;

    public SqlSessionFactoryConfig(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Bean
    public SqlSessionFactoryBean createSqlSessionFactory() {
        try {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            String packageXmlConfigPath = PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "mybatis/mapper/**/*.xml";
            // 设置 mapper 配置文件路径
            sqlSessionFactoryBean.setMapperLocations(resolver.getResources(packageXmlConfigPath));
            // 设置数据源
            sqlSessionFactoryBean.setDataSource(dataSource);
            // 设置 mybatis 配置文件路径
            sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis/mybatis-config.xml"));
            sqlSessionFactoryBean.setPlugins(new SqlDialectInterceptor(getDatabaseType(dataSource)));
            return sqlSessionFactoryBean;
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        }
    }

    private String getDatabaseType(DataSource dataSource) {
        try (Connection connection = dataSource.getConnection()) {
            DatabaseMetaData metaData = connection.getMetaData();
            String databaseProductName = metaData.getDatabaseProductName();
            loggder.info("init getDatabaseType: {}", databaseProductName);
            return databaseProductName;
        } catch (Exception ex) {
            loggder.info("init getDatabaseType error {}", ex.getMessage(), ex);
            return "mysql";
        }
    }
}
相关推荐
yige4542 分钟前
【MySQL】MySQL内置函数--日期函数字符串函数数学函数其他相关函数
android·mysql·adb
ybwycx1 小时前
springboot之集成Elasticsearch
spring boot·后端·elasticsearch
qqty12171 小时前
springboot+mybaties项目中扫描不到@mapper注解的解决方法
java·spring boot·mybatis
灵魂猎手1 小时前
14. MyBatis XML 热更新实战:告别重启烦恼
java·mybatis
星辰_mya2 小时前
InnoDB的“身体结构”:页、Buffer Pool与Redo Log的底层奥秘
数据库·mysql·spring·面试·系统架构
吾日三省Java3 小时前
SpringBoot锁设计:让你的系统不再“抢”出问题!
java·spring boot·设计思路
Rysxt_3 小时前
MySQL 触发器详解与 Navicat 实战操作指南
mysql·触发器·navicat
XXOOXRT3 小时前
Ubuntu搭建Java项目运行环境(JDK17+MySQL8.0)超详细教程
java·linux·mysql·ubuntu
tianyuanwo3 小时前
MySQL 深度解析:从核心概念到实战指南,及数据库选型决策
数据库·mysql·centos
java1234_小锋4 小时前
Java高频面试题:谈谈你对SpringBoot的理解?
java·开发语言·spring boot