想看实现直接滑倒左下边的工具类,前边在说得是解决思路

前言

现在需要向数据库中某张表中的某个字段中,插入的值为SQL语句,但是要保证插入SQL语句的正确性,而且还需要进行格式化,就像navicat中的美化SQL语句一样。

格式化

druid包中提供了SQLUtils用来格式化SQL语句,直接使用即可

导包
import com.alibaba.druid.sql.SQLUtils;
代码
@Test
    public void test2() throws ApplicationException {

        String str = "create table `tb_user` (\n" +
                "  `id` varchar(22) not null COMMENT '主键id',\n" +
                "  `usercode` varchar(11) DEFAULT null COMMENT '手机号',\n" +
                "  `name` varchar(10) DEFAULT null COMMENT '姓名',\n" +
                "  `password` varchar(20) DEFAULT null COMMENT '密码',\n" +
                "  PRIMARY KEY (`id`) USING BTREE\n" +
                ") ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;";
        System.out.println("格式化之前:");
        System.out.println(str);
        System.out.println("格式化之后:");
        System.out.println(SQLUtils.formatMySql(str));
    }
输出

java 检查json java 检查sql合法的工具类_sql格式化

如果SQL语句有错的话

java 检查json java 检查sql合法的工具类_SQLUtils_02

校验

其实校验的思路很简单,在进行格式化之前肯定需要校验SQL语句是否正确,如果不正确就报错,所以我尝试在代码中捕捉了format的错误,可是捕捉不到,继续向下进入SQLUtils中的代码当中,查看是如何实现的,发现在下层的代码中已经将此错误捕捉到了,所以不会抛出到当前这一层。

try {
            System.out.println(SQLUtils.formatMySql(str));            
        }catch (ParserException e){
            System.out.println(e.getMessage());
        }

进入SQLUtils中的sql格式化代码中

formatMySql方法

public static String formatMySql(String sql) {
        return format(sql, "mysql");
    }

继续向下进入format(String sql, String dbType)方法

public static String format(String sql, String dbType) {
        return format(sql, dbType, (List)null, (SQLUtils.FormatOption)null);
    }

继续向下进入format(String sql, String dbType, SQLUtils.FormatOption option)方法

public static String format(String sql, String dbType, SQLUtils.FormatOption option) {
        return format(sql, dbType, (List)null, option);
    }

继续向下进入format(String sql, String dbType, List parameters, SQLUtils.FormatOption option)方法

public static String format(String sql, String dbType, List<Object> parameters, SQLUtils.FormatOption option) {
        try {
            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, FORMAT_DEFAULT_FEATURES);
            List<SQLStatement> statementList = parser.parseStatementList();
            return toSQLString(statementList, dbType, parameters, option);
        } catch (ClassCastException var6) {
            LOG.warn("format error, dbType : " + dbType, var6);
            return sql;
        } catch (ParserException var7) {
            LOG.warn("format error", var7);
            return sql;
        }
    }

至此,发现被catch的错误和打印出来的错误一样。
所以,我就在想可以把这些代码直接copy出来使用,然后再进行一下catch操作。

把代码整出来

先看一看这一段代码中的一些变量是如何使用的,可以断点调试一下,看看这个方法用到了那些变量和常量,方法中的参数是不是都有用到,然后再进行提取出来就可以了。
最后提取出来是这样的,有些值是固定的,所以直接写死就行。

try {
            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, "mysql");
            List<SQLStatement> statementList = parser.parseStatementList();
            newstr = toSQLString(statementList, "mysql");
        } catch (ParserException e) {
            System.out.println(e.getMessage());
        }

整理一下就成了这样,先试一下错误的sql语句

@Test
    public void test2() throws ApplicationException {
        String str = "create table `tb_user` (\n" +
                "  `id` varchar(22) not null COMMENT '主键id',\n" +
                "  `usercode` varchar(11) DEFAULT null COMMENT '手机号',\n" +
                "  `name` varchar(10) DEFAULT nu";
        System.out.println("格式化之前:");
        System.out.println(str);
        System.out.println("格式化之后:");
        try {
            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(str, "mysql");
            List<SQLStatement> statementList = parser.parseStatementList();
            str = toSQLString(statementList, "mysql");
            System.out.println(str);
        } catch (ParserException e) {
            System.out.println("SQL转换中发生了错误:"+e.getMessage());
        }
    }

打印结果:

java 检查json java 检查sql合法的工具类_SQLUtils_03


再试一下正确的sql语句,打印结果:

java 检查json java 检查sql合法的工具类_java 检查json_04


至此,我们的校验和格式化就成功了,可以正确校验,并且格式化sql语句了。

整合工具类

最后整合成为一个工具类,会更方便一点,抛出来的异常也可以自行修改,改成自定义的也可以。

public class SqlFormatUtil {
    
    public static String sqlFormat(String sql) {
        List<SQLStatement> statementList = null;
        SQLStatementParser parser = null;
        try {
            parser = SQLParserUtils.createSQLStatementParser(sql, "mysql");
            statementList = parser.parseStatementList();
        } catch (ParserException e) {
            System.out.println("SQL转换中发生了错误:" + e.getMessage());
            throw e;
        }
        return toSQLString(statementList, "mysql");
    }

}