首先我们得理解一个新的观点:WHERE子句并不是平铺的,而是有层级的。其中,使用AND连接的查询条件是一个层级,使用OR连接的查询条件是一个层级,每一层级的条件都只能使用同一种连接符进行连接。一般情况下,多个查询条件是用AND连接的,于是默认AND作为第一层级,那么标题中的查询语句里,OR连接的两个条件就是第二层级,OR语句的第二个条件里用AND连接的两个条件就是第三层级。
使用JSON表示这样的层级结构看起来可能会清楚点:
{
"userOr": {
"id": 5,
"userAnd": {
"name": "John",
"age": 30
}
}
}
把这条数据转换为WHERE子句时可以通过键名称的后缀Or和And来确定多个子查询条件的逻辑连接符。 第一层级只有一个键userOr,可以省掉AND连接;userOr下的多个查询条件使用OR进行连接;第一个键对应条件为id=5;第二个键的多个查询条件使用AND进行连接,于是把name="John"和age=30用AND连起来;再把这个条件加上括号和id=5用OR连起来,就得到对应的查询子句:id = 5 OR (name = "John" AND age = 30)。在构造查询条件的时候可以把参数替换为占位符。
然后我们尝试使用代码来构造这样一条JSON数据:
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserQuery {
private Integer id;
private String name;
private Integer age;
private UserQuery userOr;
private UserQuery userAnd;
public static void main(String[] args) throws Exception {
UserQuery userOr = UserQuery.builder().id(5).userAnd(UserQuery.builder().name("John").age(30).build()).build();
UserQuery userQuery = UserQuery.builder().userOr(userOr).build();
ObjectMapper objectMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
System.out.println(objectMapper.writeValueAsString(userQuery));
//{"userOr":{"id":5,"userAnd":{"name":"John","age":30}}}
}
}
这样写除了麻烦点,还是可以构造出同样的JSON数据的,那么就意味着我们可以构造出同样的查询子句了。而且进一步我们会发现,这个查询条件既然能用JSON格式表示出来,那就意味着只要是支持JSON的编程语言都可以构造这样的查询条件。下一步我们就可以尝试使用不同编程语言来实现这种方案。