精华内容
下载资源
问答
  • Java使用Druid解析SQL语句

    千次阅读 2020-10-20 14:14:34
    依赖 ...版本:1.1.16 SQL语句解析 以SQLServer为例,解析插入语句和更新语句,并提取对应的数据 /** * @Author li.dongquan * @Description: SQLServer解析 ... * 解析sql语句 * * @param statement * @return

    依赖

    名称:com.alibaba.druid
    版本:1.1.16

    SQL语句解析

    以SQLServer为例,解析插入语句和更新语句,并提取对应的数据

    /**
     * @Author li.dongquan
     * @Description: SQLServer解析
     * @Date 2020/10/16
     */
    public class SqlServerParser {
    
        /**
         * 解析sql语句
         *
         * @param statement
         * @return
         */
        public void parse(String statement) {
            // 使用druid解析语句
            // 第一个参数为SQL语句
            // 第二个参数为解析的数据库类型
            List<SQLStatement> statementList = SQLUtils.parseStatements(statement, JdbcConstants.SQL_SERVER);
            // 单语句解析,只有一条数据
            if (!statement.isEmpty()) {
                SQLStatement sqlStatement = statementList.get(0);
                // 插入语句解析
                if (sqlStatement instanceof SQLServerInsertStatement) {
                    // 转换
                    SQLServerInsertStatement insertStatement = (SQLServerInsertStatement) sqlStatement;
                    // 获取列名
                    List<SQLExpr> columns = insertStatement.getColumns();
                    List<String> columnsName = new ArrayList<>(columns.size());
                    for (SQLExpr column : columns) {
                        columnsName.add(((SQLIdentifierExpr) column).getName());
                    }
                    System.out.println(columnsName);
                    // 获取值
                    List<SQLInsertStatement.ValuesClause> valuesList = insertStatement.getValuesList();
                    List<List<Object>> dataList = new ArrayList<>();
                    for (SQLInsertStatement.ValuesClause valuesClause : valuesList) {
                        List<SQLExpr> values = valuesClause.getValues();
                        List<Object> data = new ArrayList<>(columnsName.size());
                        for (SQLExpr value : values) {
                            data.add(getValue(value));
                        }
                        dataList.add(data);
                    }
                    System.out.println(dataList);
                    // 获取表名
                    System.out.println(insertStatement.getTableName().getSimpleName());
                } else if (sqlStatement instanceof SQLServerUpdateStatement) {
                    // 更新语句解析
                    SQLServerUpdateStatement updateStatement = (SQLServerUpdateStatement) sqlStatement;
                    // 获取更新的值和内容
                    List<SQLUpdateSetItem> items = updateStatement.getItems();
                    Map<String, Object> updateMap = new HashMap<>(items.size());
                    for (SQLUpdateSetItem item : items) {
                        updateMap.put(((SQLIdentifierExpr) item.getColumn()).getName(), getValue(item.getValue()));
                    }
                    System.out.println(updateMap);
                    // 获取条件,条件比较复杂,需根据实际情况自行提取
                    SQLBinaryOpExpr where = (SQLBinaryOpExpr) updateStatement.getWhere();
                    System.out.println(where);
                    // 获取表名
                    System.out.println(updateStatement.getTableName().getSimpleName());
                }
            }
            return null;
        }
    
        private static Object getValue(SQLExpr value) {
            // TODO 判断更多的种类
            if (value instanceof SQLIntegerExpr) {
                // 值是数字
                return ((SQLIntegerExpr) value).getNumber();
            } else if (value instanceof SQLCharExpr) {
                // 值是字符串
                return ((SQLCharExpr) value).getText();
            }
            return null;
        }
    
        public static void main(String[] args) throws Exception {
            SqlServerParser sqlServerParser = new SqlServerParser();
            sqlServerParser.parse("update test set status='P' where id=20");
    		sqlServerParser.parse("insert into test (id,status,name,ce,acc) values (29,'P','lll','sxsx','Arferwg')");
        }
    }
    
    

    函数解析

    SQLUtils.parseStatements(statement, JdbcConstants.SQL_SERVER);
    第一个参数为SQL语句
    第二个参数为解析的数据库类型,druid支持多种输数据库类型,只需修改数据库类型即可解析不同的SQL语句
    sqlStatement instanceof SQLServerInsertStatement
    如果是其他数据库强制转换类型也需要发生改变,例如MYSQL,则使用MySqlInsertStatement

    展开全文
  • Apache的java解析sql工具包,实现java对sql语句 的解析
  • Java 实现Sql语句解析

    千次阅读 2017-07-21 14:52:07
    最近要实现一个简易的数据库系统,除了要考虑如何高效的存储和访问数据,建立表关系外,对基本的sql查询语句要做一个解析,这样我们才能知道用户的查询要求;因为时间关系,参考了已有的一篇文章,并对其实现中出的...

    最近要实现一个简易的数据库系统,除了要考虑如何高效的存储和访问数据,建立表关系外,对基本的sql查询语句要做一个解析,这样我们才能知道用户的查询要求;因为时间关系,参考了已有的一篇文章,并对其实现中出的小问题给予更正,在这里跟大家共享一下。原文请查阅http://www.cnblogs.com/pelephone/articles/sql-parse-single-word.html

    第一步:先对sql语句进行预处理;

    对于用户,我们应该接受各种形式的查询语句书写,单行或者多行,语句中单个空格或者多个空格的间隔等等。但是我们要解析sql语句,就首先要让对它们做标准化,这样才能进行我们下一步处理。系统中的处理要求:

    1)消除SQL语句前后的空白,将其中的连续空白字符(包括空格,TAB和回车换行)替换成单个空格;

    2)将sql语句全变成小写形式(或大写形式);

    3)在SQL语句的尾后加上结束符号“ENDOFSQL”(原因后面解释)

    例如:用户输入:“select c1,c2,c3 from  t1,t2, t3 where condi1=5 and condi6=6 or condi7=7 order 

    by g1,g2”

    通过预处理应该为:“select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 order by g1,g2”

    第二步:将查询语句切分为语句块;

    以查询语句为例(本文中主要是以查询语句作为例子讲解,其它删除,插入等语句原理于此类似,因为查询语句相对复杂,所以用来i讲解),正如上面我们标准化后的语句一样,我们要进行下一步的,对表中数据的处理,首先要知道是对那些表处理,要满足那些条件,输出那些属性,以什么顺序输出等。所以查询语句就可以分割为以下几个块:

    1)select c1,c2,c3 from:属性输出块;块头(start)select,块尾(end)from,这个块我们关心的信息(body):c1,c2,c3;以下块类似分析

    2)from....where; 涉及数据表块。

    3)where.....order by; 查询条件块。

    4)order by.....ENDOFSQL; 属性输出顺序。这里也就看出了我们为什么要在查询语句末尾加上结束符,是为了最后一个块的限定需要。

    知道了如何分块,接下来要做的就是在我们已经标准化的sql语句上进行块的切割,这里我们用到了正则表达式,以第二个块from....where的查询为例,我们做个分析

    "(from)(.+)( where | on | having | group by | order by | ENDOFSQL)“

    以上就是第二个块的正则匹配式(其它块的匹配式下面也会给出),可以看出,在一个sql查询语句中,from块中跟from搭配出现的不只是where,还可以是on,having,group by等,那么通过这个正则式我们可以得到如下的块:

          from .... where

      from .... on

      from .... having

      from .... group by

      from .... order by

      from .... ENDOFSQL

    这里我们要注意一点,就是在通过正则式对sql语句进行匹配时,我们不能对整个sql语句进行一次匹配操作,因为正则匹配是贪心匹配,它总是尽可能的向后查找,匹配到最大的语句段。就拿上述语句为例,如果通过对整个sql语句进行一次匹配,得到的就不是from....where这个语句段而是from .... where .... order by。显然这不是我们想要的。所以我们只能牺牲效率,通过对整个sql语句进行逐次递增的查询方式来查找相应的语句块。给出一个查询过程,加强理解,以上述sql语句为例,对第一个语句块的查找过程是

    s
    se
    sel
    sele
    selec
    select
    select
    select c
    select c1
    select c1,
    select c1,c
    select c1,c2
    select c1,c2,
    select c1,c2,c
    select c1,c2,c3
    select c1,c2,c3
    select c1,c2,c3 f
    select c1,c2,c3 fr
    select c1,c2,c3 fro
    select c1,c2,c3 from

    这样就找到第一个块,以此类推,找第二个块时候又从头逐次递增查找。

    第三步:找到了各个块,我们还要把我们最关心的信息提取出来,就是夹在语句块头和尾之间的body部分,这个就好实现了,一般的sql语句中都会用逗号来做分割,我们提取出各个块的body信息。

    步骤介绍完了,下面就上代码,享乐吧...少年!

    package com.sitinspring.common.sqlparser.single;
    
    import java.util.List;
    
    /** *//**
    * 单句Sql解析器制造工厂
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class SqlParserUtil{
        /** *//**
         * 方法的主要入口
         * @param sql:要解析的sql语句
         * @return 返回解析结果
         */
        public String getParsedSql(String sql){
            sql=sql.trim();
            sql=sql.toLowerCase();
            sql=sql.replaceAll("\\s{1,}", " ");
            sql=""+sql+" ENDOFSQL";
            //System.out.println(sql);
            return SingleSqlParserFactory.generateParser(sql).getParsedSql();
        }
        
        /** *//**
         * SQL语句解析的接口
         * @param sql:要解析的sql语句
         * @return 返回解析结果
         */
        public List<SqlSegment> getParsedSqlList(String sql)
        {
            sql=sql.trim();
            sql=sql.toLowerCase();
            sql=sql.replaceAll("\\s{1,}", " ");
            sql=""+sql+" ENDOFSQL";
            //System.out.println(sql);
            return SingleSqlParserFactory.generateParser(sql).RetrunSqlSegments();
        }
        }
    package com.sitinspring.common.sqlparser.single;
    
    //import com.sitinspring.common.sqlparser.single.NoSqlParserException;
    import java.util.ArrayList;
    import java.util.List;
    import com.sitinspring.common.sqlparser.single.SqlSegment;
    /** *//**
    * 单句Sql解析器,单句即非嵌套的意思
    * @author 赵朝峰()
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public abstract class BaseSingleSqlParser{
    /** *//**
     * 原始Sql语句
     */
    protected String originalSql;
    /** *//**
     * Sql语句片段
     */
    protected List<SqlSegment> segments;
    /** *//**
     * 构造函数,传入原始Sql语句,进行劈分。
     * @param originalSql
     */
    public BaseSingleSqlParser(String originalSql){
        this.originalSql=originalSql;
        segments=new ArrayList<SqlSegment>();
        initializeSegments();
        splitSql2Segment();
    }
    /** *//**
     * 初始化segments,强制子类实现
     *
     */
    protected abstract void initializeSegments();
    /** *//**
     * 将originalSql劈分成一个个片段
     *
     */
    protected void splitSql2Segment() {
        for(SqlSegment sqlSegment:segments)
        {
            sqlSegment.parse(originalSql);
        }
    }
    /** *//**
     * 得到解析完毕的Sql语句
     * @return
     */
    public String getParsedSql() {
        
        //测试输出各个片段的信息
        /*
        for(SqlSegment sqlSegment:segments)
        {
            String start=sqlSegment.getStart();
            String end=sqlSegment.getEnd();
            System.out.println(start);
            System.out.println(end);
        }
        */
        
        StringBuffer sb=new StringBuffer();
        for(SqlSegment sqlSegment:segments)
        {
            sb.append(sqlSegment.getParsedSqlSegment());
        }
        String retval=sb.toString().replaceAll("@+", "\n");
        return retval;
    }
    /** *//**
    * 得到解析的Sql片段
    * @return
    */
    public List<SqlSegment> RetrunSqlSegments()
    {
        int SegmentLength=this.segments.size();
        if(SegmentLength!=0)
        {
          List<SqlSegment> result=this.segments;
          return result;
        }
        else
        {
            //throw new Exception();
            return null;
        }
    }
    }
    package com.sitinspring.common.sqlparser.single;
    
    import com.sitinspring.common.sqlparser.single.SqlSegment;
    /** *//**
    *
    * 单句删除语句解析器
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class DeleteSqlParser extends BaseSingleSqlParser{
    public DeleteSqlParser(String originalSql) {
        super(originalSql);
    }
    @Override
    protected void initializeSegments() {
        segments.add(new SqlSegment("(delete from)(.+)( where | ENDOFSQL)","[,]"));
        segments.add(new SqlSegment("(where)(.+)( ENDOFSQL)","(and|or)"));
    }
    }
    package com.sitinspring.common.sqlparser.single;
    
    import com.sitinspring.common.sqlparser.single.SqlSegment;
    /** *//**
    *
    * 单句查询插入语句解析器
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class InsertSelectSqlParser extends BaseSingleSqlParser{
    public InsertSelectSqlParser(String originalSql) {
        super(originalSql);
    }
    @Override
    protected void initializeSegments() {
        segments.add(new SqlSegment("(insert into)(.+)( select )","[,]"));
        segments.add(new SqlSegment("(select)(.+)(from)","[,]"));
        segments.add(new SqlSegment("(from)(.+)( where | on | having | groups+by | orders+by | ENDOFSQL)","(,|s+lefts+joins+|s+rights+joins+|s+inners+joins+)"));
        segments.add(new SqlSegment("(where|on|having)(.+)( groups+by | orders+by | ENDOFSQL)","(and|or)"));
        segments.add(new SqlSegment("(groups+by)(.+)( orders+by| ENDOFSQL)","[,]"));
        segments.add(new SqlSegment("(orders+by)(.+)( ENDOFSQL)","[,]"));
    }
    }
    package com.sitinspring.common.sqlparser.single;
    
    import com.sitinspring.common.sqlparser.single.SqlSegment;
    /** *//**
    *
    * 单句插入语句解析器
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class InsertSqlParser extends BaseSingleSqlParser{
    public InsertSqlParser(String originalSql) {
        super(originalSql);
    }
    @Override
    protected void initializeSegments() {
        segments.add(new SqlSegment("(insert into)(.+)([(])","[,]"));
        segments.add(new SqlSegment("([(])(.+)( [)] values )","[,]"));
        segments.add(new SqlSegment("([)] values [(])(.+)( [)])","[,]"));
    }
    @Override
    public String getParsedSql() {
        String retval=super.getParsedSql();
        retval=retval+")";
        return retval;
    }
    }
    
    复制代码
    复制代码
    
    package com.sitinspring.common.sqlparser.single;
    
    public class NoSqlParserException extends Exception{
        private static final long serialVersionUID = 1L;
        NoSqlParserException()
        {
            
        }
        NoSqlParserException(String sql)
        {
            //调用父类方法
            super(sql);
        }
    }

    package com.sitinspring.common.sqlparser.single;
    
    import com.sitinspring.common.sqlparser.single.SqlSegment;
    /** *//**
    *
    * 单句查询语句解析器
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class SelectSqlParser extends BaseSingleSqlParser{
    public SelectSqlParser(String originalSql) {
        super(originalSql);
    }
    @Override
    protected void initializeSegments() {
        segments.add(new SqlSegment("(select)(.+)(from)","[,]"));
        segments.add(new SqlSegment("(from)(.+)( where | on | having | group by | order by | ENDOFSQL)","(,| left join | right join | inner join )"));
        segments.add(new SqlSegment("(where|on|having)(.+)( group by | order by | ENDOFSQL)","(and|or)"));
        segments.add(new SqlSegment("(group by)(.+)( order by| ENDOFSQL)","[,]"));
        segments.add(new SqlSegment("(order by)(.+)( ENDOFSQL)","[,]"));
    }
    }
    package com.sitinspring.common.sqlparser.single;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    //import com.sitinspring.common.sqlparser.single.NoSqlParserException;
    /** *//**
    * 单句Sql解析器制造工厂
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class SingleSqlParserFactory{
    public static BaseSingleSqlParser generateParser(String sql)
    {
        if(contains(sql,"(insert into)(.+)(select)(.+)(from)(.+)"))
        {
            return new InsertSelectSqlParser(sql);
        }
        else if(contains(sql,"(select)(.+)(from)(.+)"))
        {
            return new SelectSqlParser(sql);
        }
        else if(contains(sql,"(delete from)(.+)"))
        {
            return new DeleteSqlParser(sql);
        }
        else if(contains(sql,"(update)(.+)(set)(.+)"))
        {
            return new UpdateSqlParser(sql);
        }
        else if(contains(sql,"(insert into)(.+)(values)(.+)"))
        {
            return new InsertSqlParser(sql);
        }
        //sql=sql.replaceAll("ENDSQL", "");
        else
            return new InsertSqlParser(sql);
           //throw new NoSqlParserException(sql.replaceAll("ENDOFSQL", ""));//对异常的抛出
    }
    /** *//**
     * 看word是否在lineText中存在,支持正则表达式
     * @param sql:要解析的sql语句
     * @param regExp:正则表达式
     * @return
     */
    private static boolean contains(String sql,String regExp){
        Pattern pattern=Pattern.compile(regExp,Pattern.CASE_INSENSITIVE);
        Matcher matcher=pattern.matcher(sql);
        return matcher.find();
    }
    }
    package com.sitinspring.common.sqlparser.single;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    /** *//**
    * Sql语句片段
    *
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class SqlSegment{
    private static final String Crlf = "@";
    private static final String FourSpace = "  ";
    /** *//**
     * Sql语句片段开头部分
     */
    private String start;
    /** *//**
     * Sql语句片段中间部分
     */
    private String body;
    /** *//**
     * Sql语句片段结束部分
     */
    private String end;
    /** *//**
     * 用于分割中间部分的正则表达式
     */
    private String bodySplitPattern;
    /** *//**
     * 表示片段的正则表达式
     */
    private String segmentRegExp;
    /** *//**
     * 分割后的Body小片段
     */
    private List<String> bodyPieces;
    /** *//**
     * 构造函数
     * @param segmentRegExp 表示这个Sql片段的正则表达式
     * @param bodySplitPattern 用于分割body的正则表达式
     */
    public SqlSegment(String segmentRegExp,String bodySplitPattern){
        start="";
        body="";
        end="";
        this.segmentRegExp=segmentRegExp;
        this.bodySplitPattern=bodySplitPattern;
        this.bodyPieces=new ArrayList<String>();
        
    }
    /** *//**
     * 从sql中查找符合segmentRegExp的部分,并赋值到start,body,end等三个属性中
     * @param sql
     */
    public void parse(String sql){
        Pattern pattern=Pattern.compile(segmentRegExp,Pattern.CASE_INSENSITIVE);
        for(int i=0;i<=sql.length();i++)
        {
         String shortSql=sql.substring(0, i);
         //测试输出的子句是否正确
         System.out.println(shortSql);
         Matcher matcher=pattern.matcher(shortSql);
         while(matcher.find())
         {
             start=matcher.group(1);
             body=matcher.group(2);
             //测试body部分
             //System.out.println(body);
             end=matcher.group(3);
             //测试相应的end部分
             //System.out.println(end);
             parseBody();
             return;
         }
        }
    }
    /** *//**
     * 解析body部分
     *
     */
    private void parseBody(){
        
        List<String> ls=new ArrayList<String>();
        Pattern p = Pattern.compile(bodySplitPattern,Pattern.CASE_INSENSITIVE);
        // 先清除掉前后空格
        body=body.trim();
        Matcher m = p.matcher(body);
        StringBuffer sb = new StringBuffer();
        boolean result = m.find();
        while(result)
        {
            m.appendReplacement(sb, m.group(0) + Crlf);
            result = m.find();
        }
        m.appendTail(sb);
        // 再按空格断行
        String[] arr=sb.toString().split(" ");
        int arrLength=arr.length;
        for(int i=0;i<arrLength;i++)
        {
            String temp=FourSpace+arr[i];
            if(i!=arrLength-1)
            {
                //temp=temp+Crlf;
            }
            ls.add(temp);
        }
        bodyPieces=ls;
    }
    /** *//**
     * 取得解析好的Sql片段
     * @return
     */
    public String getParsedSqlSegment(){
        StringBuffer sb=new StringBuffer();
        sb.append(start+Crlf);
        for(String piece:bodyPieces)
        {
            sb.append(piece+Crlf);
        }
        return sb.toString();
    }
    
    public String getBody()
    {
        return body;
    }
    
    public void setBody(String body)
    {
        this.body=body;
    }
    
    public String getEnd()
    {
        return end;
    }
    
    public void setEnd(String end)
    {
        this.end=end;
    }
    
    public String getStart()
    {
        return start;
    }
    
    
    public void setStart(String start) 
    {
        this.start=start;
    }
    
    
    }

    package com.sitinspring.common.sqlparser.single;
    
    import com.sitinspring.common.sqlparser.single.SqlSegment;
    /** *//**
    *
    * 单句更新语句解析器
    * @author 赵朝峰
    *
    * @since 2013-6-10
    * @version 1.00
    */
    public class UpdateSqlParser extends BaseSingleSqlParser{
    public UpdateSqlParser(String originalSql) {
        super(originalSql);
    }
    @Override
    protected void initializeSegments() {
        segments.add(new SqlSegment("(update)(.+)(set)","[,]"));
        segments.add(new SqlSegment("(set)(.+)( where | ENDOFSQL)","[,]"));
        segments.add(new SqlSegment("(where)(.+)( ENDOFSQL)","(and|or)"));
    }
    }
    执行结果:自己写了个测试的类
    import java.util.List;
    
    import com.sitinspring.common.sqlparser.single.*;
    public class Test {
        /** *//**
        * 单句Sql解析器制造工厂
        * @author 赵朝峰
        *
        * @since 2013-6-10
        * @version 1.00
        */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
           //String test="select  a from  b " +
               //    "\n"+"where      a=b";
           //test=test.replaceAll("\\s{1,}", " ");
           //System.out.println(test);
           //程序的入口
            String testSql="select c1,c2,c3     from    t1,t2 where condi3=3 "+"\n"+"    or condi4=5 order by o1,o2";
            SqlParserUtil test=new SqlParserUtil();
            String result=test.getParsedSql(testSql);
            System.out.println(result);
           //List<SqlSegment> result=test.getParsedSqlList(testSql);//保存解析结果
        }
    
    }
    结果为
    
    select
         c1,
         c2,
         c3
    from
          t1,
          t2
    where
      condi3=3
      or
      condi4=5
    order by
      o1,
         o2









    展开全文
  • Mybatis-Plus实现动态表名sql解析

    千次阅读 2020-09-06 22:22:16
    Mybatis-Plus实现动态表名sql解析器 添加依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</...

    Mybatis-Plus实现动态表名sql解析器

    在实现动态表名sql解析之前我们先配置动态表名的创建

    动态表名的创建

    配置mapper

    public interface SysTestMapper extends BaseMapper<SysTest> {
    
        void createTable(@Param("tableName") String tableName);
    
    }
    

    配置mapper.xml

    <mapper namespace="com.demo.studynew.mapper.SysTestMapper">
    
        <update id="createTable" parameterType="String">
            CREATE TABLE ${tableName} (
              `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
              `name` varchar(20) DEFAULT NULL,
              `gmt_create` datetime DEFAULT NULL,
              PRIMARY KEY (`id`)
            ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
      </update>
    
    </mapper>
    

    测试

     @Test
        void testCreateTable(){
    
            sysTestMapper.createTable("sys_test_2019");
        }
    

    至此动态表名的创建配置完成。

    动态表名sql解析

    添加依赖

    <dependency>
       <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.0</version>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    

    配置yml

    spring:
      servlet:
        multipart:
          max-file-size: 50MB
          max-request-size: 100MB
      datasource:
        username: root
        password: 123456
        url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF8&useSSL=false
        driver-class-name: com.mysql.jdbc.Driver
    file:
      path: /Users/jisen/Desktop
      folder: /files/
    
    ## mybatis-plus
    mybatis-plus:
      mapper-locations: classpath*:mapper/**/*.xml
      configuration:
        map-underscore-to-camel-case: true
      global-config:
        db-config:
          update-strategy: ignored
    

    编写sql解析器

    package com.demo.studynew;
    
    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
    import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    @Configuration
    @MapperScan("com.demo.studynew.**")
    public class MybatisPlusConfig {
    
        public static ThreadLocal<String> TABLE_NAME = new ThreadLocal<String>();
    
        /**
         * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
         */
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
            interceptor.addInnerInterceptor(paginationInnerInterceptor);
            DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
            Map<String, TableNameHandler> tableNameHandlerMap = new HashMap<String, TableNameHandler>();
            tableNameHandlerMap.put("sys_test", new TableNameHandler() {
                @Override
                public String dynamicTableName(String sql, String tableName) {
                    return TABLE_NAME.get();
                }
            });
            dynamicTableNameInnerInterceptor.setTableNameHandlerMap(tableNameHandlerMap);
            interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
            return interceptor;
        }
    }
    

    测试

    package com.demo.studynew;
    
    import com.demo.studynew.entity.SysTest;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.time.LocalDateTime;
    import java.util.List;
    
    
    @RestController
    @Api(tags = "动态表名测试")
    public class SysTestController {
    
        @Autowired
        private SysTestMapper sysTestMapper;
    
        @GetMapping("list")
        @ApiOperation("列表")
        public List<SysTest> list() {
            MybatisPlusConfig.TABLE_NAME.set("sys_test_2020");
            return sysTestMapper.selectList(null);
        }
    
        @GetMapping("add")
        @ApiOperation("新增")
        public String add(){
            MybatisPlusConfig.TABLE_NAME.set("sys_test_2020");
            SysTest sysTest = new SysTest();
            sysTest.setName("test1");
            sysTest.setGmtCreate(LocalDateTime.now());
            sysTestMapper.insert(sysTest);
            return "ok";
        }
    }
    

    至此动态表名sql解析完成。

    展开全文
  • atitit.java解析sql语言解析器解释器的实现 1. 解析sql的本质:实现一个4gl dsl编程语言的编译器 1 2. 解析sql的主要的流程,词法分析,而后进行语法分析,语义分析,构建sql的AST 1 3. 词法分析器 2 ...

    atitit.java解析sql语言解析器解释器的实现



    1. 解析sql的本质:实现一个4gl dsl编程语言的编译器 1

    2. 解析sql的主要的流程,词法分析,而后进行语法分析,语义分析,构建sqlAST 1

    3. 词法分析器 2

    4. 语法分析器--ANTLR 2

    5. Eclipse插件,,ANTLR Studio 3

    6. 一个基于javacc实现的解析器JSqlParser0.7(yr2011), 3

    7. 例子代码-----解析sql表格列的名称and类型 3

    8. }Sql的历史 4

    9. 解析select语句 4

    10. zqlJSqlParserGeneral sql parser. 5

    11. ANTLR实现的SQL解析器 - OQL 5

    12. Javacc/AST简单的介绍 5

    13. SQLJEP http://sqljep.sourceforge.net/ 5

    14. Sql生成SqlBuilder ,Querydsl ,hb 6

    15. 俄的总结:  还凑火JSqlParser0.7走行兰. 6

    16. 参考 6

     

    1. 解析sql的本质:实现一个4gl dsl编程语言的编译器

    Sql走十一个4gl dsl,..SQL解析器基本上走十一个编译器实现

     

    2. 解析sql的主要的流程,词法分析,而后进行语法分析,语义分析,构建sqlAST

    首先要进行词法分析,而后进行语法分析,语义分析

    词法分析,and 语法分析>>>.

    词法分析即将输入的语句进行分词(token),解析出每个token的意义。分词的本质便是正则表达式的匹配过程,比较流行的分词工具应该是lex,通 过简单的规则制定,来实现分词。Lex一般和yacc结合使用。关于lex和yacc的基础知识请参考Yacc 与Lex 快速入门- IBM。如果想深入学习的话,可以看下《LEX与YACC》。

    然而Mysql并没有使用lex来实现词法分析,但是语法分析却用了yacc,而yacc需要词法分析函数yylex,

    不过ANTLR更多简化...

     

    作者:: 老哇的爪子 Attilax 艾龙,  EMAIL:1466519819@qq.com

    转载请注明来源: http://blog.csdn.net/attilax

     

    3. 词法分析器

    MySQL的词法分析器是手工打造的。

    语法分析器的入口函数是MYSQLparse,词法分析器的入口函数是MYSQLlex。

    2. 词法分析中会检查token是否为关键字。

    最直接的做法是弄个大的关键字数组,进行折半查找

    1.1 词法分析器(Lexer)

    词法分析器又称为 Scanner,Lexical analyser和Tokenizer。程序设计语言通常由关键字和严格定义的语法结构组成。编译的最终目的是将程序设计语言的高层指令翻译成物力机器或 虚拟机可以执行的指令。此法分析器的工作是分析量化那些本来毫无意义的字符流,将他们翻译成离散的字符组(也就是一个一个的Token)括关键字,标识 符,符号(symbols)和操作符供语法分析器使用。

    ,Lexer不关心所生成的单个Token的语法意义及其与上下文之间的关系

     

    ANTLR将上述两者结合起来,它允许我们定义识别字符流的词法规则和用于解释Token流的词法分析规则。然后,ANTLR将根据用户提供的语法文件自 动生成相应的词法/语法分析器。

    4. 语法分析器--ANTLR

    也因为不想和以下推自动机为原理的YACC/LEX生成的一大堆整数表打交道,我选择了另一个开源的LL(K)语法/词法分析器—ANTLR。

    之前YACC/LEX显得过于学院派,而以LL(k)为基础的ANTLR虽然在效率上还略有不足

     

    Lexer不关心所生成的单个Token的语法意义及其与上下文之间的关系,而这就是Parser的工作。语法分析器将收到的Tokens组织起来,并转换成为目标语言语法定义所允许的序列。

    无论是Lexer还是Parser都是一种识别器,Lexer是字符序列识别器而Parser是Token序列识别器。他们在本质上是类似的东西,而只是在分工上有所不同而已。

    ANTLR将上述两者结合起来,它允许我们定义识别字符流的词法规则和用于解释Token流的词法分析规则。然后,ANTLR将根据用户提供的语法文件自 动生成相应的词法/语法分析器。用户可以利用他们将输入的文本进行编译,并转换成其他形式(如AST—Abstract Syntax Tree,抽象的语法树)。构建sql的AST

     

    5. Eclipse插件,,ANTLR Studio

     

    为了更好的使用ANTLR,你还可以下载ANTLR的Eclipse插件来帮助你完成工作。ANTLR Studio

    6. 一个基于javacc实现的解析器JSqlParser0.7(yr2011),

    它可以把SQL语句转换为Java对象,由于JsqlParser是使用JavaCC做语法分析的,而本身JavaCC就支持JJTree...如是就写了个小工具SQLParser,将生成的对象以树的形式呈现出来^

     

     

    JSqlParser存在的问题及解决 
     JSqlParser是一个SQL语句的解析器,包括常用的一些SQL语句,insert,update,select,delete等,但兼容的语法有限,比如括号,或者一些复杂的结构等。 对于转义字符的处理

     

     

    7. 例子代码-----解析sql表格列的名称and类型

    final String sql = filex.read("c:\\pojo.sql""gbk");

    new SqlParseO7(sql)

    this.sqlParseO7.parse(new Closure() 

     

     

     

    public void parse(Closure c) throws JSQLParserException {

    CCJSqlParserManager parserManager = new CCJSqlParserManager();

     

    // String statement =

    // "CREATE TABLE mytab (mycol a (10, 20) c nm g, mycol2 mypar1 mypar2 (23,323,3) asdf ('23','123') dasd, "

    // + "PRIMARY KEY (mycol2, mycol)) type = myisam";

    CreateTable createTable = (CreateTable) parserManager

    .parse(new StringReader(this.sql));

     

    List columnDefinitions = createTable.getColumnDefinitions();

    String tabName = createTable.getTable().getName();

     

    // System.out.println(columnDefinitions.size());// 获得字段总数.

    for (Object object : columnDefinitions) {

    ColumnDefinition col = (ColumnDefinition) object;

     

    Object[] oa = { col.getColumnName(),

    col.getColDataType().getDataType(), tabName };

    c.execute(oa);

     

    }

    8.  }Sql的历史

    9. 解析select语句

     

    Statement stat = new CCJSqlParserManager().parse(new StringReader( 
                            "select * from a where 姓名='崔永远'")); 
                Select select = (Select) stat; 
                Expression where = ((PlainSelect) select.getSelectBody()).getWhere(); 

                WhereExpressionVisitor visitor = new WhereExpressionVisitor(rowMeta, where); 

                for (int i = 0; i < data.length; i++) { 
                    Object result = visitor.eval(data[i]); 

                    if (result instanceof Boolean && ((Boolean) result).booleanValue()) { 
                        System.out.print("通过=====>"); 
                    } else { 
                        System.out.print("不通过=====>"); 
                    } 

                    System.out.println(StringUtils.join(data[i], ",")); 
                } 

     

    10. zqlJSqlParserGeneral sql parser. 

    11. ANTLR实现的SQL解析器 - OQL

    12. Javacc/AST简单的介绍 

    JavaCC 是一个代码生成器,可以根据输入的语言定义输出一个词法分析器和解析器,JavaCC 输出的代码是合法的可编译Java代码.解析器和词法分析器本身就是一个冗长而复杂的组件,手工编写一个这样的程序需要仔细考虑各条件的相互作用,总的来说,通过javacc完成一些字符串的分析,还是比较方便,现在普遍使用AST了。

     

    13. SQLJEP http://sqljep.sourceforge.net/

     

           SQLJEP 是一个用来解析和仿真执行SQL语句的Java类库。支持几乎所有 Oracle 和 MaxDB 的函数。SQLJEP 使用 JavaCC 来做词法分析。

     

    14. Sql生成SqlBuilder ,Querydsl ,hb

    3.SqlBuilder  http://openhms.sourceforge.net/sqlbuilder/

     

         SqlBuilder 是一个Java的类库,它试图帮你避免在Java程序内直接书写SQL查询的痛苦。你只需要使用 SqlBuilder 的方法,它就可以帮你生成对应的 SQL 数据库查询语句,例如下面一个SQL语句:

     

    15. 俄的总结:  还凑火JSqlParser0.7走行兰.

    16. 参考

    Java 实现对Sql语句解析 - 翠竹林 - 博客园.htm

    SQL 语法解释器jsqlparser - serv - ITeye技术网站.htm

     Hibernate源代码分析 - 青火的笔记 - 记笔记 - 私塾在线 - 只做精品视频课程服务.htm

    开源语法分析器--ANTLR - 薛笛的专栏 - 博客频道 - CSDN.NET.htm

     

    展开全文
  • 支持解析sql的正确性,可以解析出sql 的列名,表名,别名,条件等,非常好用
  • java 解析sql脚本

    千次阅读 2017-08-28 11:49:39
    java执行sql脚本,一种是解析sql脚本,生成每一条sql语句,由java jdbc去执行。 第二种是利用 Ant 的SQL Task来实现执行SQL 脚本的功能。http://daoshud1.iteye.com/blog/1913149 public static void main...
  • 这首先要解析出sql语句中的表,一开始想使用正则表达式,但由于不太熟悉就放弃了,在网上搜索,有网友提到java中有专门的类库JSqlParser用于解析sql语句字段,java就是方便,干啥都有类库,通过查阅其官方网站了解了...
  • java实现----sql解析

    万次阅读 2018-04-12 17:23:12
    更新中!...所以本文只是记录我学习和编写sql解析器的过程。-----------------------------------------------------------------------------------------------------------------------------------...
  • import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser; import com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor; import co....
  • javasql解析器jsqlparser.zip javasql解析器jsqlparser.zip
  • sql解析Java 7 上的 SQL 解析器 部署: mvn clean install
  • java解析sql语句

    2020-07-23 09:47:19
    String sql =“select * from (select xm,xb,nl from t_person where csrq between ? and ? and sg >= ?) t where xb =? and xm =?...我有如上一个sql字符串,如何能解析出查询字段和条件字段?
  • java8 源码 sql parser 描述 1.基于 Java8,利用 Antlr4 实现sql解析并生成解析树 2.基于解析树生成执行计划 3.基于执行计划,对 Java 内存中数据进行操作,对用户透明,并实现部分 sql 执行 4.Java 内存数据...
  • 主要介绍了Java面试题解析之判断以及防止SQL注入,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
  • 由于想要解决Mybatis分页插件中count查询效率问题,因为order by很影响...试了好几个sql解析工具,最后选择了fdb-sql-parser。 Maven依赖: com.foundationdb fdb-sql-parser 1.3.0 项目地址:https://gi
  • CS562 FinalProject-将SQL语法解析为关系表达式,然后使用maven编译并运行源代码,从而用Java实现该语法 #作者Wen Zhang 编译并运行 $ mvn测试
  • Java读取解析.sql文件

    千次阅读 2014-05-23 13:54:07
    * jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb;SelectMethod=cursor、 * jdbc:dm://localhost/system、 * jdbc:sybase:Tds:localhost:5007/myDB、 * jdbc:informix-sqli://...
  • Java工具 :SQL解析

    千次阅读 2019-01-14 20:47:32
    最近发现了一款好用的SQL解析工具,开发SQL处理类型的插件可以用到。 Git地址:https://github.com/JSQLParser/JSqlParser
  • JAVA - Sql解析工具jsqlparser简单使用

    万次阅读 热门讨论 2014-10-22 14:05:33
    jsqlparser地址:https://github.com/JSQLParser/JSqlParser ...SqlParser.jar:http://search.maven.org/remotecontent?filepath=com/github/jsqlparser/jsqlparser/0.9.1/jsqlparser-0.9.1.jar
  • Java实现HiveSQL Parser

    千次阅读 2018-11-05 15:42:56
    import com.xxxx.model.SQLParserResult... import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.ql.parse.*; import java.util.*; /** * @aut...
  • Java SQL语句解析——Jsqlparser开源项目项目需要解析SQL语句获得表名以及where中的字段,自认为自己写代码来解析比较复杂也就在网上找相关的资料,最后找到这个开源项目JSqlparser.jar包jsqlparser-0.9.1.jargithub...
  • java解析传过来的sql

    2017-07-05 07:12:07
    java后端接口中怎么解析取到传过来的sql语句groupby后面跟的字段,求代码 各位大神谢谢啦
  • Java SQL解析引擎简介

    千次阅读 2020-04-06 19:19:17
    1.QLExpress git地址:https://github.com/alibaba/QLExpress.git 文档地址:https://github.com/alibaba/QLExpress 2.JSqlParser git地址:https://github.com/JSQLParser/JSqlParser.git
  • antlr解析sql

    热门讨论 2012-05-29 09:29:10
    使用antlr规则引擎解析sql成对象.里面只有查询语句,但是也预留了update,delete,insert等语句的接口.可以非常方便的扩展
  • 项目中已使用的一个比较简单的SQL语句查询字段解析工具类
  • sql语句解析实现

    千次阅读 2016-09-09 14:48:20
    但是我们要解析sql语句,就首先要让对它们做标准化,这样才能进行我们下一步处理。系统中的处理要求: 1)消除SQL语句前后的空白,将其中的连续空白字符(包括空格,TAB和回车换行)替换成单个空格; 2)将sql...
  • 由于项目中mysql的日志格式只能选用MIXED格式(binlog存在一定的局限性,请参考),因此需要解析SQL语句。 在查找的SQL语句处理器中,都有一定的局限性,而所选中,其中一个基于javacc实现的解析器JSqlParser,使用...
  • 这篇文章主要介绍了Mybatis中的动态SQL语句解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下  Mybatis中配置SQL有两种方式,一种是利用xml 方式进行配置,...
  • 新手求助,现在做一个东西,需要将界面查询的条件进行解析sql条件,比如传进来的 条件为(!ewew&!1)&!ce|( wewe|测试) 和查询字段为content,那么得到的解析语句为 (( content not like '%ewew%' and content not ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 193,605
精华内容 77,442
关键字:

java实现动态解析sql

java 订阅