sql 分析 依赖beanutils
你还在为sql语句的拼接而烦恼吗?
sql语句支持表达式了!
package com.newland.bi.webservice.common.manage; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import org.apache.commons.beanutils.BeanUtils; import com.newland.bi.util.common.Function;
import com.newland.bi.webservice.common.model.SQLBean; /**
* 解析sql工具类
* 将 { condition ?[condition_ture]:[condition_false]} 或者 { condition ?[condition_ture]} 根据参数进行解析
* <br/>condition 可以是bean中的一个属性名eg:name,如果属性值不为null或者不等于""就返回condition_true语句,否则返回condition_false
* <br/>也可以是字符串比较的表达式 eg:name ==|!=|>|<|>=|<= wch
* <br/>支持条件的嵌套
* <br/>select * from user where 1=1 {name?[ and name=:name]} {name==wch?[name=:name]:[id=:name]}
* <br/>其中表达式中的name要是bean中属性
* @author wch
* @version 1.0
* @since 2014/05/19
*/
@SuppressWarnings("unchecked")
public class SQLUtils { /**
* 将普通javabean转换为map,属性的名值对
* @param bean
* @return map bean的属性的键值对
*/
public static Map<String, String> bean2Map(Object bean){
Map<String, String> map = new HashMap<String, String>();
try {
map = BeanUtils.describe(bean);
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
/**
* 进行解析sql语句
* <br/>{ condition ?[condition_ture]:[condition_false]} 或者 { condition ?[condition_ture]}
* <br/>
* @return 根据条件表达式替换后的语句
*/
public static String analyzeSql(Map<String, String> paramMap, String sql) { if (sql == null) {
return sql;
}
int start = 0, end = 1;
/*循环查找sql中的表达式进行解析*/
while (true) {
start = sql.lastIndexOf("{"); // 条件起始位置
end = sql.indexOf("}",start); // 条件结束位置
if (end <= start) { // 没有条件
return sql;
} String braces = sql.substring(start, end + 1);// 取得大括号的内容{...}
String braces_trim = braces;
// 处理分界符之间的空格
braces_trim = braces_trim.replaceAll("\\?\\s*\\[", "?[");
braces_trim = braces_trim.replaceAll("\\]\\s*:\\s*\\[", "]:[");
braces_trim = braces_trim.replaceAll("\\]\\s*\\}", "]}");
int question_mark_index = braces_trim.indexOf("?["); // 获取问号的位置
int colon_index = braces_trim.indexOf("]:["); // 获取冒号的位置
int end_mark_index = braces_trim.length() - 2; // ]} 的位置
if (question_mark_index == -1) {// 如果不存在问号就不进行解析
return sql;
} String condition = braces_trim.substring(1, question_mark_index); // 获取条件从{到?
String sql_true = "", sql_false = "";
if (colon_index == -1) { // 不存在冒号
sql_true = braces_trim.substring(question_mark_index + 2,
end_mark_index);// 条件为真时的语句
} else {
sql_true = braces_trim.substring(question_mark_index + 2,
colon_index);// 条件为真时的语句
sql_false = braces_trim.substring(colon_index + 3,
end_mark_index);// 添加为假时的语句
} if (isConditionTrue(paramMap, condition)) { // 判断条件是否为空
sql = sql.replace(braces, addBothSpace(sql_true));
} else {
sql = sql.replace(braces, addBothSpace(sql_false));
}
}
}
/**
* 进行解析sql语句
* <br/>{ condition ?[condition_ture]:[condition_false]} 或者 { condition ?[condition_ture]}
* @return 根据条件表达式替换后的语句
*/
public static String analyzeSql(Object bean,String sql){
return analyzeSql(bean2Map(bean), sql);
}
/**
* 如果str不为空,在str的两端添加空格,如果不存在的话
* @param str
* @return str
*/
public static String addBothSpace(String str){
if (str == null) {
return str;
}
/*添加前空格*/
if (!str.startsWith(" ")) {
str = " "+str;
}
/*添加后空格*/
if (!str.endsWith(" ")) {
str = str + " ";
}
return str;
} /**
* 根据map中的值判断condition的真假
* @param map
* @param condition
* @return
*/
private static boolean isConditionTrue(Map<String, String> map,String condition){
/*为空直接返回false*/
if (condition == null || condition.length() == 0) {
return false;
}
//去除空格
condition = condition.trim();
//匹配一个表达式
Pattern pattern = Pattern.compile("(\\w+)(?:\\s*([!><=]{1,2})\\s*(\\w+))?");
//进行匹配
Matcher matcher = pattern.matcher(condition);
if (!matcher.matches()) {
return false; //匹配不成功,直接返回false
}else { //匹配成功
String oper_left = matcher.group(1); //捕获组1,左边云算数
String oper_symbol = matcher.group(2);
String oper_right = matcher.group(3);
//属性对应的值
String value = map.get(oper_left);
if (value == null) {
return false;
}
/*存在操作符*/
if (oper_symbol != null && oper_right != null) {
return doOperate(value, oper_symbol, oper_right);
} else {
return true;
}
}
}
/**
* 进行 left symbol right的运算
* @param left
* @param symbol
* @param right
* @return
*/
private static boolean doOperate(String left,String symbol,String right){
/*不等于*/
if ("!=".equals(symbol) || "!".equals(symbol)) {
return left.compareToIgnoreCase(right) != 0;
}
/*等于*/
if ("==".equals(symbol) || "=".equals(symbol)) {
return left.compareToIgnoreCase(right) == 0;
}
/*大于等于*/
if (">=".equals(symbol)) {
return left.compareToIgnoreCase(right) >= 0;
}
/*小于等于*/
if ("<=".equals(symbol)) {
return left.compareToIgnoreCase(right) <= 0;
}
/*大于*/
if (">".equals(symbol) ) {
return left.compareToIgnoreCase(right) > 0;
}
/*小于*/
if ("<".equals(symbol)) {
return left.compareToIgnoreCase(right) < 0;
}
return false;
}
/**
* 将查询sql语句中的查询的列名,不支持*
* @param sql
* @return metaDataList
*/
public static List<String> getMetaData(String sql){
List<String> metaData = new ArrayList<String>();
if (sql == null) {
return metaData;
}
Pattern col_pattern = Pattern.compile("(\\w+)\\s*,"); // 获取列名的pattern
Pattern row_pattern = Pattern.compile("select(.*?)from"); // 获取所有列名的字符串
Matcher rowMatcher = row_pattern.matcher(sql);
if (rowMatcher.find()) {
String row = rowMatcher.group(1) + ",";
row = removeBrackets(row);
Matcher colMatcher = col_pattern.matcher(row);
// 添加列名
while (colMatcher.find()) {
metaData.add(colMatcher.group(1));
}
}
return metaData;
}
/**
* 将str 中括号里的内容去掉
* @param str
* @return 去掉括号里的内容
*/
private static String removeBrackets(String str){
if (str == null) {
return str;
}
StringBuilder sb = new StringBuilder(str);
int start = -1,end = -1;
/*从后向前查找,支持嵌套*/
start = sb.lastIndexOf("(");
while (start > -1) {
end = sb.indexOf(")", start);
if (end > -1) {
//删除掉括号的内容
sb.delete(start, end+1);
}
start = sb.lastIndexOf("(");
}
return sb.toString();
} public static void main(String[] args) {
String sql = "{id?[sql_id is not null]:[{sql==wch?[sql_id is wch]:[not wch]}]}";
SQLBean bean = new SQLBean();
bean.setSql("wc");
System.out.println("#"+analyzeSql(bean, sql)+"#");
}
}
sql 分析 依赖beanutils的更多相关文章
- MySQL SQL分析(SQL profile)
分析SQL优化运营开销SQL的重要手段.在MySQL数据库.可配置profiling参数启用SQL分析.此参数可以在全局和session水平集.级别则作用于整个MySQL实例,而session级别紧影 ...
- 分享一个基于小米 soar 的开源 sql 分析与优化的 WEB 图形化工具
soar-web 基于小米 soar 的开源 sql 分析与优化的 WEB 图形化工具,支持 soar 配置的添加.修改.复制,多配置切换,配置的导出.导入与导入功能. 环境需求 python3.xF ...
- 品味性能之道<六>:图形化SQL分析工具
在上一章里,重点分享了命令行SQL分析工具的使用方法.在本章将重点分享PL/SQL的SQL分析工具. 一.如何打开PL/SQL执行计划 开启PL/SQL这工具,推荐如下方法: 点击 ...
- 品味性能之道<五>:SQL分析工具
一.SQL语句到底是怎么执行的? 想了解SQL语句到底是怎么执行的,那就需要进行SQL语句执行计划分析. 那什么是SQL语句执行计划呢? 就是Oracle服务器执行SQL语句的过程.例如确定是否使用索 ...
- 6.7 使用show profile 进行sql分析
1. 查看是否开启 show variables like 'profiling'; 2. 开启功能 set profiling = on 3. 运行sql #写的尽量耗时的sql,利于分析 sele ...
- 转://使用showplan.sql分析sql Performance
在HelloDBA网站找到一个分析sql性能的工具—showplan,记录一下 showplan.sql下载路径:http://www.HelloDBA.com/Download/showplan.z ...
- 使用showplan.sql分析sql Performance
在HelloDBA网站找到一个分析sql性能的工具-showplan,记录一下 showplan.sql下载路径:http://www.HelloDBA.com/Download/showplan.z ...
- SqlCacheDependency:asp.net SQL缓存依赖
先看下MSDN对此类的介绍: 在以下两者之间建立关系:一是在 ASP.NET 应用程序的 Cache 对象中存储的项:二是特定 SQL Server 数据库表或 SQL Server 2005 查询 ...
- facebook Presto SQL分析引擎——本质上和spark无异,分解stage,task,MR计算
Presto 是由 Facebook 开源的大数据分布式 SQL 查询引擎,适用于交互式分析查询,可支持众多的数据源,包括 HDFS,RDBMS,KAFKA 等,而且提供了非常友好的接口开发数据源连接 ...
随机推荐
- RabbitMQ消息队列阻塞导致服务器宕机
最近工作中存储服务器由于压力太大无法及时消费消息.这个过程中,导致RabbitMQ意外挂掉,无法访问.下面是部分问题分析过程. 麒麟系统服务器分析 1.服务器异常信息: [root@localhost ...
- codevs—— 1077 多源最短路
1077 多源最短路 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 已知n个点(n<=100),给你 ...
- Ubuntu查看隐藏文件夹的方法
比如要查看当前用户目录下的隐藏文件夹 进入/home/jim目录,使用快捷键Ctrl+H,即可显示隐藏文件夹,如果要关闭,再次按Ctrl+H即可. GUI操作如下所示: 进入文件夹,左上角->查 ...
- Spring MVC集成thymeleaf时提示:defined in ServletContext resource [/WEB-INF/SrpingMVCTest-servlet.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException
错误提示: defined in ServletContext resource [/WEB-INF/SrpingMVCTest-servlet.xml]: Instantiation of bean ...
- java ee标准DataSource理解
- 如何让图片开口说话 3DMeNow教程
菜鸟玩3D--3DmeNow初级教程 3D软件对于我们这些菜鸟来说,一直是可望而不可及的一种东西,深奥的3D建模,复杂的面板操作--都使我们对之望而却步,有没有一种很简单的3D造型软件,使我们这些菜鸟 ...
- 从一个input点击引起的思考
一个input或者select标签都是有属于自己的disabled属性的,这个属性很少被使用,但是我们在项目实际开发的过程中也会遇到,比如我选择之后就让他置灰不可以变动了,那么久可利用js动态设置.对 ...
- leetcode第一刷_Spiral Matrix
我认为这个题好无聊啊,好端端一个数组.干嘛要跟比巴卜一样转一圈输出呢. . 思想非常easy,每次从左到右.再从上到下,在从右到左,再从下到上.问题是每次到什么时候该改变方向.我的做法是用一个变量保存 ...
- Android中不同方向嵌套滑动的解决方式(ListView为样例)
前言: 就像手机QQ的聊天消息列表.一个纵向滑动的ListView列举全部消息,但每一条消息能够横向滑动. 而默认情况下,仅仅能有一个地方消化处理触摸事件,要么ListView吃掉这个事件.要么子It ...
- HDOJ 题目5289 Assignment(RMQ,技巧)
Assignment Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...