用SQL查询对象(200行Java代码)
本文主要讲解SQL对象查询的实现过程。SQL4ObjQuery 实现了基本Sql查询功能:多条件过滤,分页,排序。
第三方组件使用
1. druid SQL字符串的解析
2. spring-expression 对象值读取及方法调用,表达式的
核心实现思路
- 用druid解析SQL字符串,获得SQL的结构化对象表征.
- 把SQL的条件过滤逻辑转为Stream.filter方法所需要的Predicate对象,需递归。
主要代码
/**
* execute query
* @param sql format:select * from T t where t.xx=XXX
* @param dataList data which query on
* @return T's Stream
* @throws Throwable sometime not support SQL eg:parse error,join clause,group clause will ignore
*/
public Stream<T> execute(String sql,Collection<T> dataList) throws Throwable {
System.out.println("query Collection size="+dataList.size());
// parse
List<SQLStatement> statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
// only support one select statement
SQLStatement statement = statements.get(0);
SQLSelectStatement sqlSelectStatement = (SQLSelectStatement) statement;
SQLSelectQuery sqlSelectQuery = sqlSelectStatement.getSelect().getQuery();
// not union select statement
if (sqlSelectQuery instanceof SQLSelectQueryBlock) {
this.sqlSelectQueryBlock = (SQLSelectQueryBlock) sqlSelectQuery;
//get table info
SQLTableSource from = sqlSelectQueryBlock.getFrom();
if (!(from instanceof SQLExprTableSource)) {
throw new Throwable("Sql not support! only one table");
}
this.parser = new SpelExpressionParser();
this.table=(SQLExprTableSource)from;
this.where = sqlSelectQueryBlock.getWhere();
this.stream=dataList.stream();
// See if we have any expressions that are to be executed on the Stream<T>.
this.evalWhereClause();
// Now perform the order by.
this.evalOrderByClause (sqlSelectQueryBlock.getOrderBy());
// Finally, if we have a limit clause, restrict the size of Stream<T> returned...
this.evalLimitClause ();
}
return this.stream;
}
运行:执行查询在File对象上
public static void main(String[] args) throws Throwable {
// Get a list of java.io.File objects.
File dir =new File("/Users/xx/Desktop/db/sql4object/src/main/java/fencer911/sql4object");
List<File> files = Arrays.asList(dir.listFiles());
String sql="SELECT * FROM File f WHERE f.name like '%p%.java' order by f.name ";
sql="SELECT * FROM java.io.File WHERE name like '%p%.java' and length()>1241 order by name desc ";
Stream<File> stream=new SQL4ObjQuery<File>().execute(sql,files);
System.out.println("stream.forEach");
List<File> list=stream.collect(Collectors.toList());
list.forEach(f->{
System.out.println(f.getName()+","+f.length());
});
}
项目源码地址
https://github.com/fencer911/SQL4ObjQuery