[toc]

1. JAVA中的SQL处理有什么问题吗?

看看JAVA中怎么查询数据库

public List getSelect(int id, String name) {

// sql语句

String sql = "select * from people p where p.id = ? and p.name = ?";

// 获取到连接

Connection conn = getCon();

PreparedStatement pst = null;

// 定义一个list用于接受数据库查询到的内容

List list = new ArrayList();

try {

pst = (PreparedStatement) conn.prepareStatement(sql);

ps.setint(1,id);

ps.setstring(2,name);

ResultSet rs = pst.executeQuery();

while (rs.next()) {

// 将查询出的内容添加到list中,其中userName为数据库中的字段名称

list.add(rs.getString("userName"));

}

} catch (Exception e) {

}

return list;

}

看看LISP中怎么做的

(select ((:+ 1 1)))

;=> #

(select :name

(from :person)

(where (:> :age 20)))

;=> # 20)>

(select (:id :name)

(from (:as :person :p))

(left-join :person_config :on (:= :person.config_id :person_config.id))

(where (:and (:> :age 20)

(:<= :age 65)))

(order-by :age)

(limit 5))

;=> # 20) AND (age <= 65)) ORDER BY age LIMIT 5>

(select (:sex (:count :*)) (from :person) (group-by :sex))

;=> #

(select (:sex (:as (:count :*) :num))

(from :person)

(group-by :sex)

(order-by (:desc :num)))

;=> #

2. 问题的本质是什么

JAVA处理sql的方式,与sql自己的语法格格不入, 用java写sql需要学习n个orm库的语法,以及这些库背后的设计思想。 其实这些都是多余的, 会写sql还不够吗?

在LISP中,会sql就足够了。

3. 什么是DSL

领域特定语言(英语:domain-specific language、DSL)指的是专注于某个应用程序领域的计算机语言。又译作领域专用语言。

定义2: 针对某一领域,具有受限表达性的一种计算机程序设计语言。

DSL最大的作用是屏蔽无关的噪音,专注于业务领域内的本质问题。 即只解决本质复杂度的问题,降低甚至消除偶然复杂性。

有人将DSL编程称之为声明式编程。

声明式编程:定义做什么,而不是用一堆命令语句来描述怎么做。这一点很重要。DSL就是用声明式编程。

防止DSL逐渐演变为一种通用语言,要受限表达。目的防止DSL过于复杂,可维护性降低,学习成本提升,偏离方向。

内部DSL:用通用语言的语法表示DSL,需要按照某种风格使用这种语言。

外部DSL:在主程序设计语言之外,用一种单独的语言表示领域专有语言。可以是定制语法,或者遵循另外一种语法,如XML,c make。

DSL并不是一个新的概念,实际上,从六七十年代就已经有DSL的概念了(从某种程度上来说,COBOL和FORTRAN也算是DSL,一个面向商业,一个面向科学计算),然后有RegExp,再到现在的RoR,无一不采用了DSL的思想。

4. java中的一种实现方法

private List find(Integer jobid, String state, List wellNames) throws Exception {

Page page = new Page();//初始化一个分页查询结果对象,用于接收查询结果

page.setPageSize(rows.size());//设置一页大小

PageQuery query = new PageQuery(page);//用page对象构造查询对象

query.setCount(false);//设定是否自动获取总数,如果获取的话,只会统计一次

query.addTable(WellJob.class, null);//addtable可以多次调用,用于联合查询,第二个参数是表别名,null的话表示用默认值

query.addConditon("jobType.id", OP.eq, jobid).and("state", OP.eq, state).and("well.wellNum", OP.in, wellNames);

this.pageQueryService.getNextPage(query);//获取下一页,如果page参数从页面上传回来,这个方法就是翻页了

//this.pageQueryService 对象是全局对象,基本上就是个壳,不用关心,主要功能都是在query对象里边实现的

return page.getRows();

}

看下具体怎么实现的

5. 建立这个工具的初衷

多条件查询最恶心的问题是什么?

这个问题上边的代码已经解决了,加上注释看下

private List find(Integer jobid, String state, List wellNames) throws Exception {

Page page = new Page();

page.setPageSize(rows.size());

PageQuery query = new PageQuery(page);

query.setCount(false);

query.select(xxx).from(WellJob.class, null).leftjoin(User.class, null).where("jobType.id", OP.eq, jobid).and("state", OP.eq, state).and("well.wellNum", OP.in, wellNames).leftquort().xxx().rightquort();

//addCondition 这个方法表示设置条件的开始,只能调用一次,如果第三个参数是null,则忽略这次方法调用

//add 与条件,如果第三个参数是null,忽略这次方法调用

//query 对象上基本每个api的返回值都是自身,api可以连续调用

this.pageQueryService.getNextPage(query);

return page.getRows();

}

6. 其他语言中怎么做

ruby 中一个库的用法

require 'where_builder'

f = WhereBuilder::WhereBuilder.new()

where = f.build(

f.add('a.name = ?', 'zd'),

f.OR('a.id=?', 1),

f.AND,

f.bracket(

f.add('key like ?', 'zd'),

f.AND('value=?', '2')

)

)

puts "where=#{where}"

output: where=["WHERE a.name = ? OR a.id=? AND ( key like ? AND value=?)", ["zd", 1, "zd", "2"]]

=> nil

==============================

where = f.build(

f.add('a.name = b.name'),

f.OR('a.id=?', 1),

f.AND,

f.bracket(

f.add('key like ?', 'zd'),

f.AND('value=?', '2')

)

)

=> ["WHERE a.name = b.name OR a.id=? AND ( key like ? AND value=?)", [1, "zd", "2"]]

库代码

=begin

use this tool can build a where sentence for sql, it's can ignore a condition when it's para is nil or black string.

my purpose is not check nil for every condition, don't repeat so much if else.

=end

class WhereBuilder

=begin

add first condition on 'where ..' or '(..)', you can use AND(..) or OR(..), it's ok, just ugly

cond_str: like 'a.name=?', 'a.id=b.user_id'

para: like 'leo', 123, nil

return : fn

=end

def add(cond_str, para=nil)

if (para == nil or para.to_s.strip.size == 0) and cond_str.include?('?')

return

end

#TODO in and not in

return lambda{return cond_str, para}

end

=begin

add a 'and' condition on 'where ..' or '(..)',

cond_str: like 'a.name=?', 'a.id=b.user_id' or nil, if it's nil, just append a ' AND ' str,

para: like 'leo', 123, nil

return : fn

=end

def AND(cond_str=nil, para=nil)

if cond_str == nil

return lambda{return " AND", nil}

end

if (para == nil or para.to_s.strip.size == 0) and cond_str.include?('?')

return

end

return lambda{return " AND #{cond_str}", para}

end

=begin

add a 'or' condition on 'where ..' or '(..)',

cond_str: like 'a.name=?', 'a.id=b.user_id' or nil, if it's nil, just append a ' OR ' str,

para: like 'leo', 123, nil

return : fn

=end

def OR(cond_str=nil, para=nil)

if cond_str == nil

return lambda{return " OR", nil}

end

if (para == nil or para.to_s.strip.size == 0) and cond_str.include?('?')

return

end

return lambda{return " OR #{cond_str}", para}

end

=begin

if you want add some condition with '()', use this method.

use like this :

f = WhereBuilder.new()

f.bracket(f.add(...), f.AND(...), f.AND(...))

return : fn

=end

def bracket(*args)

fn = _build_fn(*args)

return if fn == nil

para = fn.call

if para == nil || para.size == 0

return

end

return lambda{return " (#{para[0]})", para[1]}

end

=begin

do not use this method if you do't want to fix bug or upgrade this tool.

=end

def _build_fn(*args)

cond_str = []

para_list = []

size = args.size

index = 0

while index < size

fn = args[index]

if fn == nil

index += 1

next

end

typle = fn.call()

if typle == nil

index += 1

next

end

cond_str << typle[0]

if typle[1].class == Array

_index = 0

while _index < typle[1].size

para_list << typle[1][_index]

_index += 1

end

elsif typle[1] != nil

para_list << typle[1]

end

index += 1

end #while index < size

if cond_str.size == 0

return

end

if cond_str[0].strip.start_with? 'AND ' or cond_str[0].strip.start_with? 'OR '

cond1 = cond_str[0].strip

cond1 = " #{cond1[3..-1]}"

cond_str[0] = cond1

end

return lambda{return " #{cond_str.join('')}", para_list}

end

=begin

this is the enter for this tool,

use it like this :

f = WhereBuilder.new()

string, para_list = f.build(

f.add(...),

f.AND(...),

f.AND(...),

f.bracket(

f.add(...),

f.OR(...))

f.OR(...))

return : [string, para_list]

=end

def build(*args)

fn = _build_fn(*args)

if fn == nil

return ''

end

v = fn.call()

return ["WHERE#{v[0]}", v[1]]

end

end # class WhereBuilder

end

7. 一种低成本解决办法

public List findByCondition(AppQuery q) {

String sql = "SELECT x FROM App x ";

List params = new ArrayList<>();

List conds = new ArrayList();

SeviceUtils.fillNumCond("Integer", conds, params, "x.id", q.getIdOp(), q.getIdValue(), q.getIdStart(), q.getIdEnd());

SeviceUtils.fillStringCond(conds, params, "x.name", q.getNameOp(), q.getNameValue(), q.getNameStart(), q.getNameEnd());

SeviceUtils.fillStringCond(conds, params, "x.domain", q.getDomainOp(), q.getDomainValue(), q.getDomainStart(), q.getDomainEnd());

SeviceUtils.fillNumCond("Integer", conds, params, "x.parentId.id", "eq", q.getParentIdValue(), null, null);

if (conds.size() > 0) {

sql += " WHERE " + String.join(" AND ", conds);

}

sql += " ORDER BY x.id DESC";

Query query = this.entityManager.createQuery(sql);

for (int i = 0; i < params.size(); i++) {

query.setParameter(i + 1, params.get(i));

}

List infos = query.setFirstResult(q.getPageSize() * q.getPageIndex()).setMaxResults(q.getPageSize()).getResultList();

return infos;

}

serviceUtils类实现

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import javax.persistence.criteria.Predicate;

import org.springframework.util.StringUtils;

public class SeviceUtils {

public static void fillNumCond(String typeName, List conds, List params, String fname, String op, Number value,

Number start, Number end) {

try {

if (StringUtils.isEmpty(op)) {

return;

}

Object v = null;

Object s = null;

Object e = null;

if (typeName.equals("int") || typeName.equals("Integer")) {

try {

v = new Integer(value.intValue());

} catch (Exception exc) {

}

try {

s = new Integer(start.intValue());

} catch (Exception exc) {

}

try {

e = new Integer(end.intValue());

} catch (Exception exc) {

}

} else if (typeName.equals("byte") || typeName.equals("Byte")) {

try {

v = new Byte(value.byteValue());

} catch (Exception exc) {

}

try {

s = new Byte(start.byteValue());

} catch (Exception exc) {

}

try {

e = new Byte(end.byteValue());

} catch (Exception exc) {

}

} else if (typeName.equals("short") || typeName.equals("Short")) {

try {

v = new Short(value.shortValue());

} catch (Exception exc) {

}

try {

s = new Short(start.shortValue());

} catch (Exception exc) {

}

try {

e = new Short(end.shortValue());

} catch (Exception exc) {

}

} else if (typeName.equals("long") || typeName.equals("Long")) {

try {

v = new Long(value.longValue());

} catch (Exception exc) {

}

try {

s = new Long(start.longValue());

} catch (Exception exc) {

}

try {

e = new Long(end.longValue());

} catch (Exception exc) {

}

} else if (typeName.equals("float") || typeName.equals("Float")) {

try {

v = new Float(value.floatValue());

} catch (Exception exc) {

}

try {

s = new Float(start.floatValue());

} catch (Exception exc) {

}

try {

e = new Float(end.floatValue());

} catch (Exception exc) {

}

} else if (typeName.equals("double") || typeName.equals("Double")) {

try {

v = new Double(value.doubleValue());

} catch (Exception exc) {

}

try {

s = new Double(start.doubleValue());

} catch (Exception exc) {

}

try {

e = new Double(end.doubleValue());

} catch (Exception exc) {

}

}

switch (QueryOP.valueOf(op)) {

case eq:

if (v == null) {

return ;

}

conds.add(String.format(" %s=? ", fname));

params.add(v);

break;

case gt:

if (v == null) {

return ;

}

conds.add(String.format(" %s>? ", fname));

params.add(v);

break;

case lt:

if (v == null) {

return ;

}

conds.add(String.format(" %s ", fname));

params.add(v);

break;

case between:

if (s == null && e == null) {

return ;

}

if (s != null) {

conds.add(String.format(" %s>=? ", fname));

params.add(s);

}

if (e != null) {

conds.add(String.format(" %s<=? ", fname));

params.add(e);

}

break;

default:

return ;

}

return ;

} catch (Exception e) {

e.printStackTrace();

return ;

}

}

public static void fillStringCond(List conds, List params, String fname, String op, String idValue,

String idStart, String idEnd) {

try {

if (StringUtils.isEmpty(op)) {

return;

}

Predicate p2 = null;

switch (QueryOP.valueOf(op)) {

case eq:

if (idValue == null) {

return;

}

conds.add(String.format(" %s=? ", fname));

params.add(idValue);

break;

case like:

if (idValue == null) {

return;

}

conds.add(String.format(" %s LIKE ? ", fname));

params.add(idValue);

break;

case gt:

if (idValue == null) {

return ;

}

conds.add(String.format(" %s>? ", fname));

params.add(idValue);

break;

case lt:

if (idValue == null) {

return ;

}

conds.add(String.format(" %s ", fname));

params.add(idValue);

break;

case between:

if (idStart == null && idEnd == null) {

return ;

}

if (idStart != null) {

conds.add(String.format(" %s>=? ", fname));

params.add(idStart);

}

if (idEnd != null) {

conds.add(String.format(" %s<=? ", fname));

params.add(idEnd);

}

break;

default:

return;

}

return;

} catch (Exception e) {

e.printStackTrace();

return;

}

}

public static void fillEnumCond(List conds, List params, String fname, String op,

String values) {

try {

if (StringUtils.isEmpty(op)) {

return;

}

switch (QueryOP.valueOf(op)) {

case eq:

if (values == null) {

return ;

}

String[] vs = values.split(",");

List list = new ArrayList();

for (String v : vs) {

list.add(v.trim());

}

conds.add(String.format(" %s in (?) ", fname));

params.add(list);

break;

default:

return ;

}

return ;

} catch (Exception e) {

e.printStackTrace();

return ;

}

}

public static void fillBooleanCond(List conds, List params, String fname, String op,

Boolean value) {

try {

if (StringUtils.isEmpty(op)) {

return;

}

switch (QueryOP.valueOf(op)) {

case eq:

if (value == null) {

return ;

}

conds.add(String.format(" %s=? ", fname));

params.add(value);

break;

default:

return ;

}

return ;

} catch (Exception e) {

e.printStackTrace();

return ;

}

}

public static void fillDateCond(List conds, List params, String fname, String op,

Date value, Date startValue, Date endValue) {

try {

if (StringUtils.isEmpty(op)) {

return;

}

switch (QueryOP.valueOf(op)) {

case eq:

if (value == null) {

return ;

}

conds.add(String.format(" %s=? ", fname));

params.add(value);

break;

case gt:

if (value == null) {

return ;

}

conds.add(String.format(" %s>? ", fname));

params.add(value);

break;

case lt:

if (value == null) {

return ;

}

conds.add(String.format(" %s ", fname));

params.add(value);

break;

case between:

if (startValue == null && endValue == null) {

return ;

}

if (startValue != null) {

conds.add(String.format(" %s>=? ", fname));

params.add(startValue);

}

if (endValue != null) {

conds.add(String.format(" %s<=? ", fname));

params.add(endValue);

}

break;

default:

return ;

}

return ;

} catch (Exception e) {

e.printStackTrace();

return ;

}

}

}

8. 逻辑的严密性问题

​ 省掉空值会不会造成构造出来的sql发生语法错误, 没有仔细思考和证明过

java and dsl_JAVA 中SQL DSL 的一种实现方式相关推荐

  1. java map遍历_Java中Map集合的两种遍历方式

    Java中的map遍历有多种方法,从最早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下Java中Map集合的两种遍历方式! 关于遍历Map集合的几 ...

  2. java 调用枚举种方法_Java中枚举类型的一种使用方式

    今天改同事的代码发现同事的代码中有大量的if else语句.很不美观而且可读性太差. 因为需要给前端一个key,value的列表.这个列表写死.然而同事的代码. 放几张图,大家自己感受.我都不知道以后 ...

  3. java中两种遍历集合的方式_Java中Map集合的两种遍历方式

    Java中的map遍历有多种方法,从最早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下Java中Map集合的两种遍历方式! 关于遍历Map集合的几 ...

  4. Java中List集合的三种遍历方式(全网最详)

    Map集合:链接: Map集合的五种遍历方式及Treemap方法 Set集合:链接: Java中遍历Set集合的三种方法 TreeSet集合:链接: Java深入了解TreeSet,和迭代器遍历方法 ...

  5. java foreach hashmap_在 Java 中遍历 HashMap 的5种最佳方式

    在本文中,我们将通过示例讨论在 Java 上遍历  HashMap  的五种最佳方式. 使用  Iterator  遍历 HashMap EntrySet 使用  Iterator  遍历 HashM ...

  6. oracle if=,oracle中if/else的三种实现方式详解

    1.标准sql规范 1.单个IF IF v=... THEN END IF; 2.IF ... ELSE IF v=... THEN ELSE t....; END IF; 3.多个IF IF v=. ...

  7. Java集合篇:Map集合的几种遍历方式及性能测试

    文章目录 一.写在前面 二.正式开始探究之旅 1. Map集合一共有多少种遍历方式呢? 2.那这几种遍历方式的具体用法是啥样的呢? 2.1 keySet()方式遍历-------for循环 2.2 k ...

  8. java的rest教程_[Java教程]SpringMVC的REST风格的四种请求方式

    [Java教程]SpringMVC的REST风格的四种请求方式 0 2017-08-28 22:00:25 一. 在HTTP 协议里面,四个表示操作方式的动词:GET.POST.PUT.DELETE. ...

  9. Java多线程:多线程同步安全问题的 “三“ 种处理方式 ||多线程 ”死锁“ 的避免 || 单例模式”懒汉式“的线程同步安全问题

    Java多线程:多线程同步安全问题的 "三" 种处理方式 ||多线程 "死锁" 的避免 || 单例模式"懒汉式"的线程同步安全问题 每博一文 ...

最新文章

  1. 自动驾驶激光雷达物体检测技术
  2. putchar(c1)在C语言中表示,C语言中的getchar和putchar详解
  3. oracle数据库【表复制】insert into select from跟create table as select * from 两种表复制语句区别...
  4. 显示画面 大华摄像头_大华乐橙智能锁荣获2020房地产首选供应商前十强
  5. 线程,Python 实现多任务的方式之一
  6. Python稳基修炼的经典案例14(计算机二级、初学者必会字符格式处理)
  7. 解决 MyEclipse 的耗内存卡死的办法
  8. 【Three.js】模型抗锯齿处理
  9. [Android]Hello, Android!
  10. Delphi开发人员指南 第一部份快速开发的基础 第2章 Object Pascal 语言(二)
  11. word手动设置编号起始值
  12. 软件工程课程设计小组人员分工
  13. java 在线查看本地pdf文档或者图片
  14. HTML上划线 中划线 下划线实现
  15. 迪卡侬中国与阿里云达成合作;咖世家与恒天然在中国推出益生菌咖啡;默克高性能材料业务更名为电子科技 | 美通企业日报...
  16. 印度软件巨头Infosys的成功之道
  17. iOS 当APP接收到推送消息时,对推送消息进行处理
  18. PS虚化背景突出主体
  19. cocos creator休闲游戏甜品幻想H5+安卓+IOS三端源码开发脚本为javaScript
  20. 一文读懂 快速掌握示波器使用及原理

热门文章

  1. fseek()函数的用法及其理解
  2. 基于vue的高仿网易云音乐网站,实现大多数功能
  3. Aerosp­ike开发指­南【中文】
  4. 为什么AI检测器认为美国宪法是由人工智能编写的
  5. 原生js之理解作用域
  6. uTorrent端口设置
  7. Spark Streaming:RDD,Batch, Dstream, Partitiion到底是什么
  8. 机器学习的epoch、iteration和batchsize什么意思
  9. Graphviz绘制模型树2——XGBoost模型的可解释性
  10. Huffman编码MATLAB实现