当前位置: 代码网 > it编程>编程语言>Java > JSQLPARSER解析SQL知识入门

JSQLPARSER解析SQL知识入门

2024年08月01日 Java 我要评论
操作的工具包,但是发现此类文章较少,文档也不太详细,所以写个博客供参考。转换为Java类的可遍历层次结构。语法都在动态变化,可以解析某些(不是全部)。Parser就是一个把。

基础篇

jsqlparser是一个sql语句解析器。它将sql转换为java类的可遍历层次结构。 支持oracle,sqlserver,mysql,postgresql等常用数据库。但各种数据库系统的sql语法都在动态变化,可以解析某些(不是全部)。

jsqlparser就是一个把sql转换为java对象操作的工具包,但是发现此类文章较少,文档也不太详细,所以写个博客供参考。 github地址

入门

添加pom

        <dependency>
            <groupid>com.github.jsqlparser</groupid>
            <artifactid>jsqlparser</artifactid>
            <version>3.2</version>
        </dependency>

编写简单的测试

public void testselect() throws jsqlparserexception {
        // 使用工具类把sql转换为select对象
        select select = (select) ccjsqlparserutil.parse("select username,age,sex from user");
        selectbody selectbody = select.getselectbody();
        system.err.println(selectbody);
}

源码结构

expression:sql构建相关类,比如equalsto、inexpression等表达式用于构建sql

parser: sql解析相关类,比如ccjsqlparserutil。

schema:主要存放数据库schema相关的类 ,比如表、列等。

statement:封装了数据库操作对象,create、insert、delete、select等

util: 各种工具类、不同db版本、sql标准等处理类,如selectutils、databasetype等。

jsqlparser支持where及多表操作sql构建

单表where

    /**
     * 单表sql查询
     *
     * @throws jsqlparserexception
     */
    public void testselectonetable() throws jsqlparserexception {
        // 单表全量
        table table = new table("test");
        select select = selectutils.buildselectfromtable(table);
        system.err.println(select); // select * from test

        // 指定列查询
        select buildselectfromtableandexpressions = selectutils.buildselectfromtableandexpressions(new table("test"), new column("col1"), new column("col2"));
        system.err.println(buildselectfromtableandexpressions); // select col1, col2 from test

        // where =
        equalsto equalsto = new equalsto(); // 等于表达式
        equalsto.setleftexpression(new column(table, "user_id")); // 设置表达式左边值
        equalsto.setrightexpression(new stringvalue("123456"));// 设置表达式右边值
        plainselect plainselect = (plainselect) select.getselectbody(); // 转换为更细化的select对象
        plainselect.setwhere(equalsto);
        system.err.println(plainselect);//  select * from test where test.user_id = '123456'

        // where  != <>
        notequalsto notequalsto = new notequalsto();
        notequalsto.setleftexpression(new column(table, "user_id")); // 设置表达式左边值
        notequalsto.setrightexpression(new stringvalue("123456"));// 设置表达式右边值
        plainselect plainselectnot = (plainselect) select.getselectbody();
        plainselectnot.setwhere(notequalsto);
        system.err.println(plainselectnot);//  select * from test where test.user_id <> '123456'

        // 其他运算符, 参考上面代码添加表达式即可
        greaterthan gt = new greaterthan(); // ">"
        greaterthanequals geq = new greaterthanequals(); // ">="
        minorthan mt = new minorthan(); // "<"
        minorthanequals leq = new minorthanequals();// "<="
        isnullexpression isnull = new isnullexpression(); // "is null"
        isnull.setnot(true);// "is not null"
        likeexpression nlike = new likeexpression();
        nlike.setnot(true); // "not like"
        between bt = new between();
        bt.setnot(true);// "not between"

        // where like
        likeexpression likeexpression = new likeexpression(); // 创建like表达式对象
        likeexpression.setleftexpression(new column("username")); // 表达式左边
        likeexpression.setrightexpression(new stringvalue("张%")); // 右边表达式
        plainselect plainselectlike = (plainselect) select.getselectbody();
        plainselectlike.setwhere(likeexpression);
        system.err.println(plainselectlike); // select * from test where username like '张%'

        // where in
        set<string> deptids = sets.newlinkedhashset(); // 创建in范围的元素集合
        deptids.add("0001");
        deptids.add("0002");
        itemslist itemslist = new expressionlist(deptids.stream().map(stringvalue::new).collect(collectors.tolist())); // 把集合转变为jsqlparser需要的元素列表
        inexpression inexpression = new inexpression(new column("dept_id "), itemslist); // 创建in表达式对象,传入列名及in范围列表
        plainselect plainselectin = (plainselect) select.getselectbody();
        plainselectin.setwhere(inexpression);
        system.err.println(plainselectin); // select * from test where dept_id  in ('0001', '0002')

        // where between and
        between between = new between();
        between.setbetweenexpressionstart(new longvalue(18)); // 设置起点值
        between.setbetweenexpressionend(new longvalue(30)); // 设置终点值
        between.setleftexpression(new column("age")); // 设置左边的表达式,一般为列
        plainselect plainselectbetween = (plainselect) select.getselectbody();
        plainselectbetween.setwhere(between);
        system.err.println(plainselectbetween); // select * from test where age between 18 and 30

        //  where and 多个条件结合,都需要成立
        andexpression andexpression = new andexpression(); // and 表达式
        andexpression.setleftexpression(equalsto); // and 左边表达式
        andexpression.setrightexpression(between);  // and 右边表达式
        plainselect plainselectand = (plainselect) select.getselectbody();
        plainselectand.setwhere(andexpression);
        system.err.println(plainselectand); //  select * from test where test.user_id = '123456' and age between 18 and 30

        //  where or 多个条件满足一个条件成立返回
        orexpression orexpression = new orexpression();// or 表达式
        orexpression.setleftexpression(equalsto); // or 左边表达式
        orexpression.setrightexpression(between);  // or 右边表达式
        plainselect plainselector = (plainselect) select.getselectbody();
        plainselector.setwhere(orexpression);
        system.err.println(plainselector); // select * from test where test.user_id = '123456' or age between 18 and 30

        // order by 排序
        orderbyelement orderbyelement = new orderbyelement(); // 创建排序对象
        orderbyelement.isasc(); //  设置升序排列 从小到大
        orderbyelement.setexpression(new column("col01")); // 设置排序字段
        plainselect plainselectorderby = (plainselect) select.getselectbody();
        plainselectorderby.addorderbyelements(orderbyelement);
        system.err.println(plainselectorderby); // select * from test where test.user_id = '123456' or age between 18 and 30 order by col01
    }

多表join

    /**
     * 多表sql查询
     * join / inner join: 如果表中有至少一个匹配,则返回行
     * left join: 即使右表中没有匹配,也从左表返回所有的行
     * right join: 即使左表中没有匹配,也从右表返回所有的行
     * full join: 只要其中一个表中存在匹配,就返回行
     */
    public void testselectmanytable() {
        table t1 = new table("tab1").withalias(new alias("t1").withuseas(true)); // 表1
        table t2 = new table("tab2").withalias(new alias("t2", false)); // 表2
        plainselect plainselect = new plainselect().addselectitems(new allcolumns()).withfromitem(t1); // select * from tab1 as t1

        // join on 如果表中有至少一个匹配,则返回行
        join join = new join(); // 创建join对象
        join.withrightitem(t2); // 添加join的表 join t2 =>join tab2 t2
        equalsto equalsto = new equalsto(); // 添加 = 条件表达式  t1.user_id  = t2.user_id
        equalsto.setleftexpression(new column(t1, "user_id "));
        equalsto.setrightexpression(new column(t2, "user_id "));
        join.withonexpression(equalsto);// 添加on
        plainselect.addjoins(join);
        system.err.println(plainselect); // select * from tab1 as t1 join tab2 t2 on t1.user_id  = t2.user_id

        // 设置join参数可实现其他类型join
        // join.setleft(true); left join
        // join.setright(true);  right join
        // join.setfull(true); full join
        // join.setinner(true);
    }

sql函数

    /**
     * sql 函数
     * select function(列) from 表
     */
    public void testfun() throws jsqlparserexception {
        table t1 = new table("tab1").withalias(new alias("t1").withuseas(true)); // 表1
        plainselect plainselect = new plainselect();
        plainselect.setfromitem(t1); // 设置from t1= >  select  from tab1 as t1
        list<selectitem> selectitemlist = new arraylist<>(); // 查询元素集合
        selectexpressionitem selectexpressionitem001 = new selectexpressionitem(); // 元素1表达式
        selectexpressionitem001.setexpression(new column(t1,"col001"));
        selectexpressionitem selectexpressionitem002 = new selectexpressionitem(); // 元素2表达式
        selectexpressionitem002.setexpression(new column(t1,"col002"));
        selectitemlist.add(0, selectexpressionitem001); // 添加入队
        selectitemlist.add(1, selectexpressionitem002); // 添加入队

        // count
        selectexpressionitem selectexpressionitemcount = new selectexpressionitem(); // 创建函数元素表达式
        selectexpressionitemcount.setalias(new alias("count")); // 设置别名
        function function = new function(); // 创建函数对象  function extends astnodeaccessimpl implements expression
        function.setname("count"); // 设置函数名
        expressionlist expressionlistcount = new expressionlist(); // 创建参数表达式
        expressionlistcount.setexpressions(collections.singletonlist(new column(t1, "id")));
        function.setparameters(expressionlistcount); // 设置参数
        selectexpressionitemcount.setexpression(function);
        selectitemlist.add(2,selectexpressionitemcount);

        plainselect.setselectitems(selectitemlist); // 添加查询元素集合入select对象
        system.err.println(plainselect); // select t1.col001, t1.col002, count(t1.id) as count from tab1 as t1
    }

jsqlparser进行sql解析

import net.sf.jsqlparser.jsqlparserexception;
import net.sf.jsqlparser.expression.expression;
import net.sf.jsqlparser.expression.function;
import net.sf.jsqlparser.expression.operators.relational.namedexpressionlist;
import net.sf.jsqlparser.parser.ccjsqlparserutil;
import net.sf.jsqlparser.schema.column;
import net.sf.jsqlparser.schema.table;
import net.sf.jsqlparser.statement.statement;
import net.sf.jsqlparser.statement.create.table.createtable;
import net.sf.jsqlparser.statement.delete.delete;
import net.sf.jsqlparser.statement.insert.insert;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.statement.update.update;
import net.sf.jsqlparser.statement.values.valuesstatement;
import net.sf.jsqlparser.util.tablesnamesfinder;
import org.apache.commons.collections.collectionutils;
import sun.net.www.content.text.plain;

import java.util.list;
import java.util.objects;

public class main {

    static string sql1 = "select t1.f1,t1.f2,t2.id,count(*) from table t1 left join table1 t2 right join (select * from table2) t3 where t1.id='12121' or (t1.id between 1 and 3 and t1.id>'22112') group by t.f1 order by t.f1 desc,tf2 asc limit 1,20";
    static string sql2 = "insert into table(f1,f2) values (1,2)";
    static string sql2_1 = "insert into table(f1,f2) (select f1,f2 from table1)";
    static string sql3 = "update table set f1=2,f2=3 where f1=1212";
    static string sql3_1 = "insert into table(f1,f2) (select f1,f2 from table1)";
    static string sql4_1 = "delete from table where 1=1";
    static string sql_5 = "create table table_name2 as select * from table_name1 t1 where t1.id = '333'";
    static string sql5_1 = "create table `gen_table` (\n" +
            "  `table_id` bigint(20) not null auto_increment comment '编号',\n" +
            "  `table_name` varchar(200) default '' comment '表名称',\n" +
            "  `table_comment` varchar(500) default '' comment '表描述',\n" +
            "  `sub_table_name` varchar(64) default null comment '关联子表的表名',\n" +
            "  `sub_table_fk_name` varchar(64) default null comment '子表关联的外键名',\n" +
            "  `class_name` varchar(100) default '' comment '实体类名称',\n" +
            "  `tpl_category` varchar(200) default 'crud' comment '使用的模板(crud单表操作 tree树表操作 sub主子表操作)',\n" +
            "  `package_name` varchar(100) default null comment '生成包路径',\n" +
            "  `module_name` varchar(30) default null comment '生成模块名',\n" +
            "  `business_name` varchar(30) default null comment '生成业务名',\n" +
            "  `function_name` varchar(50) default null comment '生成功能名',\n" +
            "  `function_author` varchar(50) default null comment '生成功能作者',\n" +
            "  `gen_type` char(1) default '0' comment '生成代码方式(0zip压缩包 1自定义路径)',\n" +
            "  `gen_path` varchar(200) default '/' comment '生成路径(不填默认项目路径)',\n" +
            "  `options` varchar(1000) default null comment '其它生成选项',\n" +
            "  `create_by` varchar(64) default '' comment '创建者',\n" +
            "  `create_time` datetime default null comment '创建时间',\n" +
            "  `update_by` varchar(64) default '' comment '更新者',\n" +
            "  `update_time` datetime default null comment '更新时间',\n" +
            "  `remark` varchar(500) default null comment '备注',\n" +
            "  primary key (`table_id`)\n" +
            ") engine=innodb default charset=utf8 comment='代码生成业务表';";
    static string sql1_1 = "select `t2a_cust_c`.`cust_id` as `cust_id`,`t2a_cust_c`.`cust_name` as `cust_name`,`t2a_cust_c`.`cust_en_name` as `cust_en_name`,`t2a_cust_c`.`cust_sts` as `cust_sts`,`t2a_cust_c`.`cust_type` as `cust_type`,`t2a_cust_c`.`cert_type` as `cert_type`,`t2a_cust_c`.`cert_no` as `cert_no`,`t2a_cust_c`.`org_id` as `org_id`,`t2a_cust_c`.`biz_scope` as `biz_scope`,'' as `nation_cd`,null as `income_amt`,`t2a_cust_c`.`create_dt` as `create_dt`,'' as `is_staff`,`t2a_cust_c`.`is_free_trade` as `is_free_trade`,`t2a_cust_c`.`cust_nat` as `cust_nat`,`t2a_cust_c`.`pbc_indus` as `pbc_indus`,'' as `pbc_ocp`,`t2a_cust_c`.`cert_invalid_dt` as `cert_invalid_dt` from `t2a_cust_c` union all select `t2a_cust_i`.`cust_id` as `cust_id`,`t2a_cust_i`.`cust_name` as `cust_name`,`t2a_cust_i`.`cust_en_name` as `cust_en_name`,`t2a_cust_i`.`cust_sts` as `cust_sts`,`t2a_cust_i`.`cust_type` as `cust_type`,`t2a_cust_i`.`cert_type` as `cert_type`,`t2a_cust_i`.`cert_no` as `cert_no`,`t2a_cust_i`.`org_id` as `org_id`,'' as `biz_scope`,`t2a_cust_i`.`nation_cd` as `nation_cd`,`t2a_cust_i`.`income_amt` as `income_amt`,`t2a_cust_i`.`create_dt` as `create_dt`,`t2a_cust_i`.`is_staff` as `is_staff`,`t2a_cust_i`.`is_free_trade` as `is_free_trade`,`t2a_cust_i`.`cust_nat` as `cust_nat`,'' as `pbc_indus`,`t2a_cust_i`.`pbc_ocp` as `pbc_ocp`,`t2a_cust_i`.`cert_invalid_dt` as `cert_invalid_dt` from `t2a_cust_i`";

    public static void main(string[] args) {
        testsimpleselectsql(sql1_1);
//        testsimpleinsertsql(sql2);
//        testsimpleinsertsql(sql2_1);
//        testsimpleupdatesql(sql3);
//        testsimpledeletesql(sql4_1);
//        testsimplecreatesql(sql5_1);
    }

    private static void testsimplecreatesql(string sql_5) {
        try {
            statement statement = ccjsqlparserutil.parse(sql_5);
            if (statement instanceof createtable) {
                table table = ((createtable) statement).gettable();
                system.out.println(table);
                select select = ((createtable) statement).getselect();
                if (select != null){
                    string s = select.tostring();
                    testsimpleselectsql(s);
                }
            }
        } catch (exception e) {
            e.printstacktrace();
        }
    }

    //解析sql
    public static void testsimpleselectsql(string sql1) {
        system.out.println("=================测试查询==================");
        try {
            select select = (select) ccjsqlparserutil.parse(sql1);
            tablesnamesfinder tablesnamesfinder = new tablesnamesfinder();
            list<string> tablelist = tablesnamesfinder.gettablelist(select);
            // 获取到查询sql中的所有表名,下面的逻辑是对sql的细致拆分
            system.out.println("表名:" + tablelist);
            if (select.getselectbody() instanceof plainselect) { // 普通查询
                // 复杂sql会多次调用此处方法,所以抽出作为公共类使用
               getselectmsg(select);
            }else if (select.getselectbody() instanceof withitem){ // with语句

            }else if (select.getselectbody() instanceof setoperationlist){ // intersect、except、minus、union语句
               setoperationlist setoperationlist =  (setoperationlist)select.getselectbody();
                list<selectbody> selects = setoperationlist.getselects();
                for (int i = 0; i < selects.size(); i++) {
                    // 此处又是符合普通sql的拆解逻辑
                    getselectmsg(select);
                }
            }else if (select.getselectbody() instanceof valuesstatement){ // values语句

            }
        } catch (jsqlparserexception e) {
            e.printstacktrace();
        }
        system.out.println("=================测试查询==================");
    }

    public static void testsimpleinsertsql(string sql) {
        system.out.println("=================测试插入sql==================");
        system.out.println("测试sql:" + sql);
        try {
            insert insert = (insert) ccjsqlparserutil.parse(sql);
            system.out.println("插入的表" + insert.gettable());
            system.out.println("插入的列" + insert.getcolumns());
            if (objects.nonnull(insert.getselect())) {
                selectbody selectbody = insert.getselect().getselectbody();
                system.out.println("来自:" + selectbody);
            } else {
                system.out.println("普通插入");
                system.out.println("插入的值" + insert.getitemslist());
            }

        } catch (jsqlparserexception e) {
            e.printstacktrace();
        }

        system.out.println("=================测试插入sql==================");
    }

    public static void testsimpleupdatesql(string sql) {
        system.out.println("=================测试更新sql==================");
        system.out.println("测试sql:" + sql);
        try {
            update update = (update) ccjsqlparserutil.parse(sql);
            system.out.println("更新的表" + update.gettable());
            system.out.println("更新的列" + update.getcolumns());
            system.out.println("更新的值" + update.getexpressions());
            system.out.println("条件" + update.getwhere());
        } catch (jsqlparserexception e) {
            e.printstacktrace();
        }

        system.out.println("=================测试更新sql==================");
    }

    public static void testsimpledeletesql(string sql) {
        system.out.println("=================测试删除sql==================");
        system.out.println("测试sql:" + sql);
        try {
            delete delete = (delete) ccjsqlparserutil.parse(sql);
            system.out.println("删除的表" + delete.gettable());
            system.out.println("条件的列" + delete.getwhere());
        } catch (jsqlparserexception e) {
            e.printstacktrace();
        }

        system.out.println("=================测试删除sql==================");
    }

    public static string jointypestr(join join) {
        if (join.isleft()) {
            return "左连接";
        }
        if (join.isright()) {
            return "左连接";
        }
        if (join.isfull()) {
            return "全连接";
        }
        if (join.iscross()) {
            return "交叉连接";
        }
        return null;
    }

    public static void getselectmsg(select select){
        plainselect plain = (plainselect) select.getselectbody();
        list<join> joins = plain.getjoins();
        if (collectionutils.isnotempty(joins)) {
            for (join join : joins) {
                fromitem rightitem = join.getrightitem();
                if (rightitem instanceof table) {
                    table table = (table) (rightitem);
                    system.out.println("连接类型:" + jointypestr(join) + "         表:" + table.getname() + "           别名:" + table.getalias());
                } else if (rightitem instanceof subselect) {
                    subselect subselect = (subselect) (rightitem);
                    system.out.println("连接类型:" + jointypestr(join) + "         子查询:" + subselect.getselectbody() + "           别名:" + rightitem.getalias());
                }
            }
        }
        list<selectitem> selectitems = plain.getselectitems();
        for (selectitem selectitem : selectitems) {
            if (selectitem instanceof allcolumns) {
                system.out.println("获取的是表中的全部列:  * ");
                continue;
            }
            selectexpressionitem selectexpressionitem = (selectexpressionitem) selectitem;
            expression expression = selectexpressionitem.getexpression();
            //判断表达式是否是函数
            if (expression instanceof function) {
                function function = (function) expression;
                namedexpressionlist namedparameters = function.getnamedparameters();
                if (namedparameters != null) {
                    list<expression> expressions = namedparameters.getexpressions();
                    system.out.println(expressions);
                }
                system.out.println("函数:" + ((function) expression).getname());
                boolean allcolumns = function.isallcolumns();
                system.out.println("传入的是全部列:" + allcolumns);
                //判断表达式是否是列
            } else if (expression instanceof column) {
                system.out.println("查询值:" + ((column) expression).getcolumnname());
            }
        }
//        system.out.println("表名:" + tablelist);
        expression where = plain.getwhere();
        if (where != null) {
            system.out.println("条件:" + where);
        }

        //排序
        list<orderbyelement> orderbyelements = plain.getorderbyelements();
        if (objects.nonnull(orderbyelements)) {
            for (orderbyelement orderbyelement : orderbyelements) {
                expression expression = orderbyelement.getexpression();
                if (expression instanceof column) {
                    column column = (column) (expression);
                    system.out.println("排序字段:" + column.getcolumnname() + "," + (orderbyelement.isasc() ? "正序" : "倒序"));
                }
            }
        }


        //获取分组
        groupbyelement groupby = plain.getgroupby();
        if (objects.nonnull(groupby)) {
            list<expression> groupbyexpressions = groupby.getgroupbyexpressions();
            for (expression groupbyexpression : groupbyexpressions) {
                if (groupbyexpression instanceof column) {
                    column column = (column) (groupbyexpression);
                    system.out.println("分组字段:" + column.getcolumnname());
                }
            }
        }

        //分页
        limit limit = plain.getlimit();
        if (objects.nonnull(limit)) {
            system.out.println("行:" + limit.getrowcount());
            system.out.println("偏移量:" + limit.getoffset());
        }
    }
}

 

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com