概述
什么是 Nutz.Dao 中的复杂SQL条件
对于 Nutz.Dao 来说,它本质上就是将你的 Java 对象转化成 SQL,然后交给 JDBC 去执行。
而 SQL 中,当执行数据删除和查询操作时,最常用的就是 WHERE 关键字。
WHERE 关键字后面的就是所谓的复杂查询条件
Nutz.Dao 将如何如何使用这个条件
Dao 接口的 clear 方法和 query 方法的第二个参数,就是为了生成 WHERE 后面那段字符串设计的
这个参数是一个 org.nutz.dao.Condition 接口的实现类
通过该接口的 toSql(org.nutz.dao.entity.Entity) 方法, Nutz.Dao 将获得 WHERE 后面那段字符串
当然也包括 ORDER BY
Condition 接口
这个接口只有一个方法toSql(Entity> entity)
这个方法带一个参数 org.nutz.dao.entity.Entity
通过这个参数,实现者可以获得当前需要操作的实体的配置信息
当然,如果你不需要的话,你可以不理睬这个参数
Nutz.Dao 会将toSql(Entity> entity) 的返回直接拼接到SQL 的 WHERE 关键字后面
如果你返回的字符串以 WHERE 或者 ORDER BY 开头,它会直接使用,否则会补上一个 WHERE 关键字
这个判断会忽略前后空白以及大小写
Nutz 给你的快速实现
如果你的数据库字段被假设不会发生变化,用直接硬编码是个很好的选择
如果在开发期,你的数据库字段变化非常频繁,用 Cnd 工具类则是更好的选择
一个友好的工具类 -- Cnd
有些情况,数据库中的字段同 Java 对象中的字段并不同名,
所以就需要给 Java 字段上的数据库字段注解加上参数 @Column("数据库字段名")
如果你通过 Cnd.wrap() 硬编码某个字段,那么当这个字段数据库字段名发生改变时,你就需要改动很多。
因此你希望仅仅将对于数据库的变动限制在 Java 对象的源文件里
所以 Nutz 提供了 Cnd.where() 方法
Condition c = Cnd.where("age",">",30).and("name", "LIKE", "%K%").asc("name").desc("id");
这个条件将生成 SQL
WHERE age>30 AND name LIKE '%K%' ORDERBY name ASC, id DESC
你也可以嵌套表达式
SqlExpressionGroup e1 = Cnd.exps("name", "LIKE", "P%").and("age", ">", "20");
SqlExpressionGroup e2 = Cnd.exps("name", "LIKE", "S%").and("age", "
Condition c = Cnd.where(e1).or(e2).asc("name");
这个条件将生成 SQL
WHERE (name LIKE 'P%' AND age>'20') OR (name LIKE 'S%' AND age
直接硬编码(不推荐)
最暴力的方法就是直接输出 WHERE 关键字后面的 SQL 代码了。比如查询一个 Person 对象
List crowd = dao.query(Person.class, Cnd.wrap("name LIKE 'J%' AND age>20"), null);
部分暴力,使用Static
// 筛选年龄(age)小于20,现金(cash字段)多于负债(due字段)的XX
List list = dao.query(Girl.class, Cnd.where("age", " due")));
拼装更加复杂的条件
上面的例子的 Cnd.where 函数,在大多数情况下可以快速的生成一个简单的查询条件。但是,如果查询条件非常复杂,
用它可能就比较费劲了。是的,它的设计初衷就是 "查询条件应该一行搞定"。
有些时候,查询条件很复杂,一行确实搞不定,怎么办?Nutz-1.b.38 以后,提供了 Criteria 接口,它继承自
Condition 接口,它的设计目的有两个:让程序员更容易的拼装复杂逻辑的条件
让生成的 SQL 可以被参数化,更好的支持 PreparedStatement
这个接口的使用也很简单,它基本符合 "IDE 的所见即所得" 接口设计原则。 就是说,如果你的 IDE 有智能提示的话,
你使用这个接口是不需要文档的。
// 创建一个 Criteria 接口实例
Criteria cri = Cnd.cri();
// 组装条件
if(...){
cri.where().andIn("id", 3,4,5).andIn("name", "Peter", "Wendal", "Juqkai");
}else if(...){
cri.where().andLT("id", 9);
}else if(...){
cri.where().andInBySql("关联字段","select id from 关联表 where name = '%s'",变量);
}else if(...){
cri.where().andInBySql("关联字段","select id from 关联表 where name like '%%%s%%'",变量);
}
if(...){
cri.where().andLike("name", "%A%");
}
cri.getOrderBy().asc("name").desc("id");
// 执行查询
List list = dao.query(MyObj.class, cri, null);
Criteria 的 where() 函数返回的是 SqlExpressionGroup,主要由它来提供各种 SQL 条件的组合方法。
这里需要给出一点提示,比如方法名 andGT,表示的是 andGreatThan,即
"大于" 的意思,同理:LT : 小于 (LessThan)
GTE : 大于等于 (GreatThanEqual)
LTE : 小于等于 (LessThanEqual)
模糊查询的小提示
如下代码,当str的长度大于1和等于1时的行为有差异
Cnd cnd = Cnd.where("name", "like", str);
// 若str的长度为1,输出的SQL是
// where name like "%a%"
// 若str的长度为2,输出的SQL是
// where name like "ab"
正确的写法是
Cnd cnd = Cnd.where("name", "like", "%" + str + "%s");