背景
公司的框架是基于mysql5.7开发的,最近有一个利用我的项目部署在linux零碎上,应用的是mysql8.0,装置时未开启大小写敏感疏忽,客户又不容许重装mysql环境,导致一些框架代码和业务代码中表名应用大写的中央会呈现表名找不不到的状况,所以须要进行对立解决
自定义SQLAST适配器
自定义ASTVisitorAdapter对表名进行批改
public class MySqlExportTableAliasVisitor extends MySqlASTVisitorAdapter { @Override public boolean visit(SQLExprTableSource x) { SystemConfig systemConfig = SpringBootBeanUtil.getBean(SystemConfig.class); if(systemConfig.getDbTableNameProxy().equals("lowcase")){ x.setExpr(x.getTableName().toLowerCase()); }else if(systemConfig.getDbTableNameProxy().equals("upcase")){ x.setExpr(x.getTableName().toUpperCase()); } return true; }}
自定义Mybatis拦截器
通过BoundSql获取sql语句,应用Druid的SQLUtils对sql语句进行结构化分析,表名批改实现后再从新复制sql语句
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})public class SQLTableNameHandleInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { DataBaseInfoUtil dataBaseInfoUtil = SpringBootBeanUtil.getBean(DataBaseInfoUtil.class); if(dataBaseInfoUtil.checkOpenTableNameHandle()){ StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory()); BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql"); String sql = boundSql.getSql(); List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); MySqlExportTableAliasVisitor visitor = new MySqlExportTableAliasVisitor(); for (SQLStatement stmt : stmtList) { stmt.accept(visitor); } String handleSQL = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL); metaStatementHandler.setValue("delegate.boundSql.sql", handleSQL); } return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { }}
注册自定义Myabits拦截器
@Configurationpublic class FrameMyBatisPluginConfig { @Bean @Conditional({SQLTableNameHandleInterceptorCondition.class}) public String SQLTableNameHandleInterceptor(SqlSessionFactory sqlSessionFactory) { //实例化插件 SQLTableNameHandleInterceptor sqlTableNameHandleInterceptor = new SQLTableNameHandleInterceptor(); //创立属性值 Properties properties = new Properties(); properties.setProperty("prop1","value1"); //将属性值设置到插件中 sqlTableNameHandleInterceptor.setProperties(properties); //将插件增加到SqlSessionFactory工厂 sqlSessionFactory.getConfiguration().addInterceptor(sqlTableNameHandleInterceptor); return "interceptor"; }}