想看实现直接滑倒左下边的工具类,前边在说得是解决思路
前言
现在需要向数据库中某张表中的某个字段中,插入的值为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));
}
输出
如果SQL语句有错的话
校验
其实校验的思路很简单,在进行格式化之前肯定需要校验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());
}
}
打印结果:
再试一下正确的sql语句,打印结果:
至此,我们的校验和格式化就成功了,可以正确校验,并且格式化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");
}
}