
## 一、什么是 QFilter
`QFilter` 是 ORM 引擎查询时使用的条件对象,最终会翻译为 SQL 的 `where` 部分(即下图中的 constraint_expression)。
```sql
SELECT TOP COUNT DISINCT column, AGG_FUNC(column_or_expression), ...
FROM mytable
JOIN another_table
ON mytable.column = another_table.column
WHERE constrant_expression -- QFilter 会翻译成 constrant_expression 部分
GROUP BY column
HAVING constrant_expression
ORDER BY column ASC | DESC
```
### 1. 支持的条件语句
使用 QFilter 能够满足 SQL 查询中使用到的条件语句。
- QCP 结合构造方法创建
- 大于 `QCP.large_than`
- 小于 `QCP.less_than`
- 等于 `QCP.equals`
- 大于等于 `QCP.large_equals`
- 小于等于 `QCP.less_equals`
- 不等于 `QCP.not_equals` `QCP.not_equals2`
- in `QCP.in`
- not in `QCP.not_in`
- 静态方法创建
- like
- not like
- is null
- is not null
除了基本的 SQL 条件查询,QFilter 还提供了一些具有特定过滤的方法,有关更多信息,可以查看后面的章节。
## 二、QFilter 简单使用
创建 QFilter 主要有两种方式:
- QFilter 构造方法
- 静态方法创建 like、not like、is null、is not null 以及特殊过滤的 QFilter
### 1. 构造方法创建 QFilter
使用构造方法 QFilter(String, String, Object)创建常用的 QFilter,需要使用QCP中定义的比较符。
```java
// a > 100
QFilter f0 = new QFilter("a", QCP.large_than, 100);
// b = 'xx'
QFilter f1 = new QFilter("b", QCP.equals, "xx");
// c < 100
QFilter f2 = new QFilter("c", QCP.less_than, 100);
...
```
### 2. 静态方法创建 QFilter
静态方法主要用来创建特定查询的 QFilter,通常会有特定的规则或者限制,使用时需要了解其特性,主要有以下方法:
#### 1) like、not like
like(String, String) 、notLike(String, String) 即为 SQL 中的 `like`、`not like` ,如果值没有加 `%`、`_` 通配符则自动在值的前后加 `%` 。
```java
// name like '%tom%'
QFilter f = QFilter.like("name", "tom");
// name like 'tom%'
QFilter f = QFilter.notLike("name", "tom%");
```
#### 2) is null、is not null
与 SQL 中的 `is null` 与 `is not null` 判断条件一致,查看isNull(String) isNotNull(String)
```java
// name is null
QFilter f = QFilter.isNull("name");
```
```java
// name is not null
QFilter f = QFilter.isNotNull("name");
```
#### 3) exists、not exists
使用exists(String, QFilter) 与 notExists(String, QFilter) 则可实现我们所知的 SQL 中的 exists 语义。
SQL 的 `exists`、`not exists` 查询有两种情况:
1. 子查询与外表的字段没有关系,只要子查询的条件成立,则会查询所有外表的数据。
2. 子查询与外表的字段有关系,此时 SQL 类似一个关联查询,会查询外表的数据然后去匹配子查询中的结果。
QFilter 提供的 exists 查询只有第 2 种情况,在 ORM 查询语境下即实体引用对象的查询与实体有关系,这也符合 ORM 本身基于实体查询的特性。
#### 4) ftlike、ftlikeMultiValue
通过 `全文索引`进行模糊查询,使用时需要开启平台全文索引特性。有关全文索引更多信息,请参阅全文索引相关章节。
> WIKI全文索引:从文本或数据库中,不限定资料字段,自由地萃取出信息的技术。
ftlike(String, String...)属性之间为 or 关系,值之间为 or 关系
```java
QFilter f = QFilter.ftLike(new String[]{"x", "y"}, "f1", "f2")
```
```mysql
(f1 like '%x%' or f1 like '%y%') or (f2 like '%x%' or f2 like '%y%')
```
ftlikeMultiValue(String, String...)属性之间为 or 关系,值之间为 and 关系
```java
QFilter f = QFilter.ftlikeMultiValue(new String[]{"x y", "1 2"}, "f1", "f2")
```
```mysql
(f1 like '%x%' AND f1 like '%y%' OR f1 like '%1%' AND f1 like '%2%' OR f2 like '%x%' AND f2 like '%y%' OR f2 like '%1%' AND f2 like '%2%')
```
#### 5) 实体的引用对象为空
exists(String)与notExists(String)方法用于需要判断实体对应的引用属性(基础资料、分录等)是否存在。
> 这里的 exists 方法与上文中 SQL 的 exists 语法没有任何关系,只是方法同名。
ORM 都是基于实体的查询,传入参数需要是实体关联对象的主键,这样 ORM 才能正确解析。
```java
String pk = "creator.id";
QFilter f1 = QFilter.exists(pk);
QFilter f2 = QFilter.notExists(pk);
// 数据库存储外键是有规范,为空使用 0 或 " " 不能是 null 值 。
// 翻译 QFilter.exists(pk)
// 当 pk 为分录或子分录主键时, pk is not null
// 当 pk 为基础资料外键时: pk != 0 or pk != ''
```
QFilter 还提供了一种判断引用对象的具体属性为空的场景:
假如想要判断引用对象上的某个字段为空,而使用上面的方法仅能判断引用对象为空,这时候就需要用到
emptyOrNotExists(String),使用方法也很简单,入参只要传入引用对象的某个属性。
```java
String name = "creator.name";
QFilter f1 = QFilter.emptyOrNotExists(name);
// 翻译
// 当 name 为分录或子分录的属性时, pk is null or 分录(子分录).name = '' or 分录(子分录).name is null
// 当 name 为基础资料的属性时: pk = 0 or pk = '' or 基础资料.name = '' or 基础资料.name is null
```
#### 6) 包含空数据
引用对象的属性不满足某个条件,如 `not in` 、`