Dorado 5 : 8.Dataset的查询原理 (T1)

在DBDataset(AutoSqlDataset和SqlDataset)中,最显著的特征就是执行Dataset数据集对象加载数据的过程即是执行SQL查询语句并返回查询结果集的过程。而条件过滤查询则是动态拼装where条件语句执行SQL查询并最终返回过滤后的结果集的过程。特别地,SqlDataset是在监听器的beforeLoadData方法中实现动态拼装SQL语句。

MatchRules匹配规则

在AutoSqlDataset中,MatchRules对于过滤查询起到了至关重要的作用,它主要用于定义SQL语句中的where。一般在开发使用AutoSqlDataset参与的查询中,为了实现不同条件下的不同结果,我们通常会配置不同的MatchRule组合。
MatchRule分为三种:

  • BaseMatchRule

基本的匹配规则,前面所介绍的都属于此种。

  • AndOrMatchRule

设置过滤查询中where部分的查询条件之间采用哪种关系,可选择and或or。没有特别声明指定时,默认各查询条件之间的关系是and。

  • SqlMatchRule

并非所有的应用都是查询条件的关联如此简单,在where查询条件部分也可能会出现较复杂的子查询、或加入数据库本身提供的特殊函数及计算公式。SqlMatchRule可摆脱BaseMatchRule的限制,实现更加复杂多样的查询匹配规则。
通常应用较多的是BaseMatchRule,本书中涉及到AutoSqlDataset的过滤查询也都采用此种方式。例如定义了datasetEmployee数据集中关于EMPLOYEE_ID的MatchRule,默认情况下,数据加载所执行的SQL语句是:

SELECT 
	 EMPLOYEE.EMPLOYEE_ID, 
	 EMPLOYEE.DEPT_ID, 
	 EMPLOYEE.EMPLOYEE_NAME, 
	 EMPLOYEE.SEX, 
	 EMPLOYEE.BIRTHDAY, 
	 EMPLOYEE.MARRIED, 
	 EMPLOYEE.SALARY 
	 FROM 
	 EMPLOYEE 
	 WHERE 
	 (EMPLOYEE.EMPLOYEE_ID = ?)


如果再设置DEPT_ID的MatchRule,数据加载所执行的SQL语句是:

SELECT 
	 EMPLOYEE.EMPLOYEE_ID, 
	 EMPLOYEE.DEPT_ID, 
	 EMPLOYEE.EMPLOYEE_NAME, 
	 EMPLOYEE.SEX, 
	 EMPLOYEE.BIRTHDAY, 
	 EMPLOYEE.MARRIED, 
	 EMPLOYEE.SALARY 
	 FROM 
	 EMPLOYEE 
	 WHERE 
	 (EMPLOYEE.EMPLOYEE_ID = ?) and (EMPLOYEE.DEPT_ID = ?)


可以看出,设置了MatchRule之后,执行的SQL语句被添加了where,并且新增的条件默认是采用and连接的。显而易见,为了实现过滤查询而设置的where条件,如果不赋值将无法查询到任何结果。在之前的例子中,我们已经看到设置MatchRule之后刷新页面,却没有任何数据被加载展现出来。为了解决第一次加载的时候数据无法出现的问题,我们在示例中的解决办法是设置所有MatchRule的escapeEnable属性值为true,这是为什么呢?这就要讲到escapeEnable和escapeValue两个属性的原理。

  • escapeEnable 可逃逸

该属性值为true时表示允许逃逸,false则不允许逃逸。在AutoSqlDataset加载数据时,当escapeEnable属性值为true(允许逃逸),设置的MatchRule匹配规则中指定的escapeValue(逃逸值)与提供的该匹配规则的匹配参数值一致时,该条MatchRule匹配规则无效,即不添加至where条件中。反之,则添加至where条件中。大多数情况下,在页面刷新后第一次加载Dataset中的数据时,我们没有设置过escapeValue的属性值,也没提供相对应的匹配值,设置允许逃逸时,全部数据被加载出来(即匹配规则无效,不添加至where条件中)。默认情况下,没有赋值即意味着值为$null。该属性和escapeValue属性结合使用。
如果了解iBatis框架的话,你会发现它与其中的isNotEmpty十分相似。

  • escapeValue 逃逸值

该属性值的设置如果与提供的MatchRule匹配规则的参数值一致,且允许逃逸时,可使得该MatchRule匹配规则无效。

Parameters参数集

Dataset中的Parameters参数集对象通常被用于从客户端传递预定义设置的值到服务器端处理。在AutoSqlDataset中,Parameters参数集还承担了动态为MatchRule匹配规则赋值的功能。
我们前面讲到AutoSqlDataset设置MatchRule匹配规则需要提供赋值才能实现条件过滤查询,这个赋值就是由Parameters提供的。二者之间的关联是通过MatchRule的value属性进行匹配的。
设置AutoSqlDataset的MatchRule匹配规则时,为了能接受传递的匹配赋值,通常需要在其value属性值中设置":(英文冒号)+匹配关键字"这样格式的匹配规则。如果AutoSqlDataset可以自动将Parameters中设置的参数值与对应的MatchRule关联赋值,那么它们之间的匹配关键字必须一致。例如设置了MatchRule的value属性值为:EMPLOYEE_ID,则在Parameters中必须存在一个parameter参数对象,该参数对象的name必须是EMPLOYEE_ID,即与MatchRule中设置的一致才可以一一对应起来,通常它们之间的数据类型也应该一致。
特别地,Parameters参数集中的parameter参数对象可以在Studio中被显式地创建出来,也可以通过dataset.parameters().setValue(key,value)的方式动态赋值。

过滤查询原理图

  1. AutoSqlDataset中parameter参数对象的name必须和MatchRule中value设置值冒号后的关键字一致(图①)。
  2. AutoSqlDataset中parameter参数对象的value将会根据匹配的结果进行赋值,该值被作为MatchRule匹配查询条件值加入到where查询中(图②)。
  3. 如果parameter参数对象中value属性值与escapeValue设置逃逸值一致,且允许逃逸。则该MatchRule匹配规则无效,不会被添加至where查询中(图③)。


当AutoSqlDataset在服务器端初始化时,我们可以在Dataset监听器的beforeLoadData方法中对其进行改造从而实现自定义的数据加载方式,即没有加载数据之前执行自定义加载操作。其中,页面刷新、flushData方法、Dataset的查询以及其他可能触发数据重新加载的动作都会触发上述流程的执行。