使用java sql parser插件Jsqlparser 实例(二)

来源:互联网 发布:mac装windows iso 编辑:程序博客网 时间:2024/06/01 17:55

     JsqlParser插件用来对于SQL语句进行解析和组装,将SQL语句关键词之间的内容用List<String>进行保存,同时可以进行更改List<String>的内容后重新组装成一个新的SQL语句。项目中的需求多用于更改SQL中table name。(其实感觉用正则会更好一点) JsqlParser其实就是将sql语句各个关键词用Java类的形式进行了对应解析,包括很多函数可以让我们得到各个部分的内容 

    熟悉了Jsql插件的一些基本使用情况以后,发现还有一些不足,目前把这几天写的东西放上来了。解决一些这样的问题:

   1.给定的SQL语句是否满足基本语法问题?——我尝试将String转化为statement将Jsql的异常信息保存,并提取有效信息,返回错误单词+位置信息

   2.insert语句批量插入数据的修改————正则匹配values并保存到List<List<Stirng>>中,replace函数替换原来SQL完成重新组装。

   后面给出具体解决方法,并总结了一些知识。


  1.Jsql异常信息的抛出以及正则匹配的知识

// 获取sql语句中的所有表名// 可以获取任意类型sql语句的全部表名,这里使用的select sql// **********传入String 得到List<String>,嵌套已测试public static List<String> test_select_table(String sql)throws JSQLParserException {Statement statement = (Statement) CCJSqlParserUtil.parse(sql);Select selectStatement = (Select) statement;TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();List<String> tableList = tablesNamesFinder.getTableList(selectStatement);return tableList;}// 验证sql语法正确性,返回错误信息// 传入 String sql// ***********返回错误信息such as: “错误单词” “line 1” “column 80”public static String judge_type(String sql) {try {Statement statement = (Statement) CCJSqlParserUtil.parse(sql);} catch (JSQLParserException e) {ByteArrayOutputStream baos = new ByteArrayOutputStream();e.printStackTrace(new PrintStream(baos));String exception = baos.toString();String regEx = "Encountered(.*)";Pattern pat = Pattern.compile(regEx);Matcher mat = pat.matcher(exception);while (mat.find()) {exception = mat.group(1);}// System.out.println(exception);String line = "";String regEx2 = "line (.*),";pat = Pattern.compile(regEx2);mat = pat.matcher(exception);while (mat.find()) {line = mat.group(1);}// System.out.println(line);int line_num = Integer.valueOf(line).intValue();int indexofcolumn = exception.indexOf("column");String errornumber = exception.substring(indexofcolumn + 7,exception.length() - 1);int error_num = Integer.valueOf(errornumber).intValue();System.out.println(error_num);String ERROR_location = "";if (error_num != 1) {String sql_sub = sql.substring(0, error_num - 2); // 发生错误位置前面的字符串// 错误信息单词往往处于错误位置的前一个地方单词// 获取错误位置两个前面两个空格之间的单词,并保存sql_sub = new StringBuilder(sql_sub).reverse().toString();int indexofspace = sql_sub.indexOf(" ");String sql_error = sql_sub.substring(0, indexofspace);sql_error = new StringBuilder(sql_error).reverse().toString();ERROR_location = "\"" + sql_error + "\"" + " at line "+ line_num + " at column " + error_num;} else {int indexofspace = sql.indexOf(" ");String sql_error = sql.substring(0, indexofspace);ERROR_location = "\"" + sql_error + "\"" + " at line "+ line_num + " at column " + error_num;}return ERROR_location; // 错误信息的返回}String result = "correct";return result; // Jsql可以解析,返回correct}
总结:

1.group()组,正则子表达式概念
2.matcher,只有执行了find()方法 后,状态机matcher才是真正开始进行匹配工作的

3.捕获try catch语句中的异常信息,保存到String中去。关键函数e.printStackTrace


2..insert语句批量插入数据的修改

// insert时获取所有values(批量插入情况) insert table1(c1,c2)// values(v1,v2),(v11,v22),(v111,v222)public static List<List<String>> insert_values(String sql)throws JSQLParserException {Statement statement = CCJSqlParserUtil.parse(sql);String exception = statement.toString();System.out.println(exception);List<List<String>> str_values = new ArrayList<List<String>>();String regEx1 = "VALUES(.*)|ON DUPLICATE KEY UPDATE$";Pattern pat = Pattern.compile(regEx1);Matcher mat = pat.matcher(exception);while (mat.find()) {exception = mat.group(1).toString();}String regEx2 = "(?<=\\().*?(?=\\))";pat = Pattern.compile(regEx2);mat = pat.matcher(exception);while (mat.find()) {exception = mat.group(0).toString();List<String> str_list = new ArrayList<String>();// System.out.println(exception);String str = "";// 将Values 每一个括号内部的string 按照 ,分割开来。并加入到List<String>for (int i = 0, j = 0; j < exception.length() - 1; j++) {if (exception.charAt(j) == ',') {str = exception.substring(i, j);// System.out.println(str);i = j + 1;str_list.add(str);}if (j == exception.length() - 2) {str = exception.substring(i, j + 2);// System.out.println(str);str_list.add(str);}}// List<List<Stirng>>.addstr_values.add(str_list);}return str_values;}

// 组装insert   //批量Values的组装,//参数:要修改的sql语句,已经得到的新的List<List<Stirng>>//将原来的Values替换为新参数public static String build_insert_values(String sql,List<List<String>> str_values) throws JSQLParserException {//这里相当于 字符串转化大写   与  单空格间隔 的格式化,方便后面替换Statement statement = CCJSqlParserUtil.parse(sql);String exception = statement.toString();String exception_delete = "";String replacement = "";String regEx = "VALUES(.*)";Pattern pat = Pattern.compile(regEx);Matcher mat = pat.matcher(exception);while (mat.find()) {exception_delete = mat.group(1).toString();}boolean start_out = true;//为二维string添加  逗号和括号for (int i = 0; i < str_values.size(); i++) {boolean start_in = true;String brackets = "";for (int j = 0; j < str_values.get(i).size(); j++) {if (start_in == true) {brackets += str_values.get(i).get(j);// System.out.println(brackets);start_in = false;} elsebrackets += "," + str_values.get(i).get(j);}brackets = "(" + brackets + ")";if (start_out == true) {replacement = brackets;start_out = false;} elsereplacement += "," + brackets;}//最后加上分号replacement += ";";// System.out.println(replacement);exception = exception.replace(exception_delete, replacement);sql = exception;return sql;}}



0 0
原创粉丝点击