Java解析SQL的基本思路

这篇具有很好参考价值的文章主要介绍了Java解析SQL的基本思路。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

天天在写sql,一直很好奇sql到底咋解析的,于是随便整个小demo。

比如sql是:

String sql = "select name,score,sex from users where name = 'jack' and isdelete <> 1 ; ";

中间可能有1个或者多个空格,就想着怎么着也得有个分词的类,就叫做Tokenizer吧。

public class Tokenizer implements Iterator<String> {

    String[] tokens;
    int index = 0;

    public Tokenizer(String sql) throws BadSqlGrammarException {
        sql = sql.trim();
        if (!sql.endsWith(";")) {
            throw new BadSqlGrammarException("SQL未正确结束!");
        }
        //去除多余的空格
        sql = sql.replace(";", " ;").replaceAll("\\s+", " ");
        //分词
        tokens = sql.split(" ");
    }


    @Override
    public boolean hasNext() {
        return index < tokens.length;
    }

    @Override
    public String next() {
        return tokens[index++];
    }

}

这是一个名为Tokenizer的Java类,实现了Iterator接口。它用于将输入的SQL语句进行分词。

构造函数Tokenizer(String sql)接受一个SQL语句作为参数,并对其进行处理。首先,它去除了字符串两端的空格,并检查SQL语句是否以分号结尾。如果不是以分号结尾,则抛出一个BadSqlGrammarException异常。

接下来,它使用正则表达式替换将分号替换为空格加分号,并将多个连续的空格替换为单个空格。然后,它使用空格作为分隔符,将SQL语句分割成一个字符串数组tokens。

hasNext()方法用于判断是否还有下一个分词。它通过比较index和tokens数组的长度来确定是否还有剩余的分词。

next()方法用于返回下一个分词。它返回tokens数组中index位置的元素,并将index加1,以便指向下一个分词。

实现Iterator是因为需要去遍历维护的String数组,方便后面解析。

然后是parser类,里面聚合一个Tokenizer的引用。

public class Parser {

    Tokenizer tokenizer;
    DBCmd cmd;
    
    Map<String, DBCmd> cmdMap = new HashMap<>();
    public Parser(String sql) throws BadSqlGrammarException {
        //用查表法,代替一大堆的if else
        this.cmdMap.put("select", new SelectCmd());
        this.tokenizer = new Tokenizer(sql);

        //根据第一个sql关键字来确定是什么sql命令
        this.cmd = this.cmdMap.get(tokenizer.next());

        if (cmd == null)
            throw new BadSqlGrammarException("未识别的sql命令!");

    }


    public void query() throws BadSqlGrammarException {
        cmd.query(tokenizer);
    }

}

这是一个名为Parser的Java类,用于解析SQL语句并执行相应的数据库命令。

该类包含以下成员变量和方法:

  1. tokenizer:一个Tokenizer对象,用于将输入的SQL语句分解为多个标记(tokens)。

  2. cmd:一个DBCmd对象,表示要执行的数据库命令。

  3. cmdMap:一个HashMap,用于将SQL关键字与对应的DBCmd对象进行映射。

构造函数Parser(String sql)用于初始化Parser对象。它接受一个SQL语句作为参数,并根据第一个SQL关键字确定要执行的数据库命令。具体步骤如下:

  1. 创建一个HashMap对象cmdMap,并将"select"关键字与SelectCmd对象进行映射。

  2. 创建一个Tokenizer对象,并将输入的SQL语句作为参数传递给它。

  3. 使用Tokenizer的next()方法获取SQL语句的第一个关键字,并通过cmdMap获取对应的DBCmd对象。

  4. 如果cmd为null,表示未识别的SQL命令,抛出BadSqlGrammarException异常。

query()方法用于执行数据库查询操作。它调用cmd对象的query()方法,并将Tokenizer对象作为参数传递给它。

总之,Parser类通过查表法将SQL关键字与对应的数据库命令进行映射,实现了SQL语句的解析和执行。

DBCmd做成一个抽象类,不同的命令需要单独设计一个类,去继承他。DBCmd就弄一些通用的方法即可。

public abstract class DBCmd {

    public abstract void query(Tokenizer tokenizer) throws BadSqlGrammarException;

    protected String splitUntilEnd(Tokenizer tokenizer) throws BadSqlGrammarException {
        return splitUntil(tokenizer, ";");
    }


    protected String splitUntil(Tokenizer tokenizer, String until) throws BadSqlGrammarException {
        StringBuffer sb = new StringBuffer();

        boolean find = false;
        while (tokenizer.hasNext()) {
            String next = tokenizer.next();
            if (!next.equals(until)) {
                sb.append(next).append(" ");
                continue;
            } else {
                find = true;
                break;
            }
        }
        if (!find)
            throw new BadSqlGrammarException("语法不正确");
        return sb.toString();
    }
}

这段代码是一个Java类,名为DBCmd。它是一个抽象类,意味着不能直接实例化,只能被其他类继承。

该类有一个抽象方法query,接受一个Tokenizer对象作为参数,并且可能会抛出BadSqlGrammarException异常。这个方法在子类中需要被实现。

类中还有两个受保护的方法:splitUntilEnd和splitUntil。这两个方法都接受一个Tokenizer对象和一个字符串作为参数,并且可能会抛出BadSqlGrammarException异常。

splitUntilEnd方法调用了splitUntil方法,并传入了分隔符";"。splitUntilEnd方法的作用是将Tokenizer对象中的字符串逐个读取,直到遇到分隔符";"为止,并将读取的字符串拼接成一个新的字符串返回。

splitUntil方法是一个循环,它不断从Tokenizer对象中读取字符串,如果读取的字符串不等于给定的分隔符until,则将字符串拼接到StringBuffer对象sb中,并在每个字符串之间添加一个空格。如果读取的字符串等于分隔符until,则循环结束,并返回拼接好的字符串。

如果循环结束后仍然没有找到分隔符until,则抛出一个BadSqlGrammarException异常,表示语法不正确。

总的来说,这段代码定义了一个抽象类DBCmd,其中包含了一些用于处理SQL语句的方法。子类可以继承该类,并实现query方法来执行具体的SQL查询操作。

只测试一下select语法,所以只写一个select操作类。

public class SelectCmd extends DBCmd {

    @Override
    public void query(Tokenizer tokenizer) throws BadSqlGrammarException {
        String querys = splitUntil(tokenizer, "from");
        String tableName = tokenizer.next();
        String condition = null;
        if (tokenizer.hasNext() && tokenizer.next().equals("where")) {
            condition = splitUntilEnd(tokenizer);
        }
        System.out.println("查询字段:" + querys);
        System.out.println("查询表:" + tableName);
        System.out.println("查询条件:" + condition);

    }


}

最后测试一下子:

public static void main(String[]args)throws BadSqlGrammarException{
        String sql="select  name,score,sex from    users where name = 'jack' and isdelete <> 1   ;  ";
        Parser parser=new Parser(sql);
        parser.query();

}

效果:

查询字段:name,score,sex 查询表:users 查询条件:name = 'jack' and isdelete <> 1文章来源地址https://www.toymoban.com/news/detail-528427.html

到了这里,关于Java解析SQL的基本思路的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 程序员最终会被自己开发的轮子所淘汰吗?

    螺丝刀和扳手的发明,并没有让工人下岗; 工程机械(挖掘机等)的发明,也不会让建筑工人的需求量减少; 现代医学的各种先进设备,似乎也没有让医生数量大幅减少; …… 所以,关于“程序员最终会被自己开发的轮子而淘汰自己吗?”这个命题, 我的回答是不会。 能

    2024年02月05日
    浏览(36)
  • JSP 学生成绩查询管理系统eclipse开发sql数据库serlvet框架bs模式java编程MVC结构

    一、源码特点   JSP 学生成绩查询管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,比较流行的servlet框架系统具有完整的源代码和数据库,eclipse开发系统主要采用B/S模式 开发。 java 学生成绩查询管理系统 代码下载链接 https://download.csdn.net/download/qq_412

    2024年02月05日
    浏览(67)
  • SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录(第三天)动态SQL

    昨天我们深入学习了 Mybatis的核心对象SqlSessionFactoryBuilder , 掌握MyBatis核心配置文件以及元素的使用 ,也掌握MyBatis映射文件及其元素的使用。那么今天我们需要掌握的是更加复杂的查询操作。 学会编写MyBatis中动态SQL 学会MyBatis的条件查询操作 学会MyBatis的更新操作 学会MyBati

    2024年02月11日
    浏览(54)
  • 【SQL Server】数据库开发指南(七)MS-SQL存储过程全面解析:种类、优点和创建方法详解

    本系列博文还在更新中,收录在专栏:#MS-SQL Server 专栏中。 本系列文章列表如下: 【SQL Server】 Linux 运维下对 SQL Server 进行安装、升级、回滚、卸载操作 【SQL Server】数据库开发指南(一)数据库设计的核心概念和基本步骤 【SQL Server】数据库开发指南(二)MSSQL数据库开发对

    2024年02月07日
    浏览(105)
  • Java解析JSON复杂数据的第三种思路

    本文介绍了Java解析JSON复杂数据的第三种思路,通过改变思路,按照新的流程获取数据。文章详细解析了接口JSON数据,并提供了JSON转XML数据

    2024年01月25日
    浏览(64)
  • 【SQL Server】数据库开发指南(一)数据库设计的核心概念和基本步骤

    本系列博文还在更新中,收录在专栏:#MS-SQL Server 专栏中。 本系列文章列表如下: 【SQL Server】 Linux 运维下对 SQL Server 进行安装、升级、回滚、卸载操作 【SQL Server】数据库开发指南(一)数据库设计的核心概念和基本步骤 【SQL Server】数据库开发指南(二)MSSQL数据库开发对

    2024年02月09日
    浏览(74)
  • 华为OD机试 -矩阵扩散(Java) | 机试题+算法思路+考点+代码解析 【2023】

    存在一个mn的二维数组,其成员取值范围为0或1。其中值为1的成员具备扩散性,每经过1S,将上下左右值为0的成员同化为1。二维数组的成员初始值都为0,将第[i,j]和[k,l]两个个位置上元素修改成1后,求矩阵的所有元素变为1需要多长时间。 输入描述: 输出数据中的前2个数字表

    2024年02月16日
    浏览(61)
  • Java后端sql编写

    在后端编写sql,不要直接编写sql语句进行查询 比如直接在service实现类中写下图这种语句 三级目录

    2024年01月16日
    浏览(39)
  • Java 正则匹配sql

    在线正则校验 加^$的话就代表把整个要匹配的字符串当成一个整体做一次匹配, 而不加则一个字符串可以匹配多次,代表这个字符串中有符合条件的 如\\\"^abc$\\\"只能匹配abc;\\\"abc\\\"不仅可以匹配abc,还可以匹配abcd

    2024年02月22日
    浏览(34)
  • Java实现SQL分页

    在日常开发需要对数据进行分页,配置如下 编写配置类  在控制器层可以加上之后使用 了解如下  大致流程如下 在控制器中注入业务层实现方法时需要加上参数IPage 在Service中实现将Ipage传入Mapper文件中  在mapper层中加入参数Ipage实现分页 结果如下 上面是使用mybatis-puls实现分

    2024年02月08日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包