zoukankan      html  css  js  c++  java
  • Fun论设计模式之4:标准模式(Criteria Pattern)与MyBatis的Example原理

      标准模式,又叫过滤器模式(Filter Pattern),这个设计模式在我们常用的工具里面会大量体现,尤其是在数据处理方面,但我们却很难发现。

      意图:允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。

      主要解决:对象运算过程的直觉化。

      何时使用:当您想让对象本身进行运算,并且方法可串一起运行。

      如何解决:使用的方法在对象内部进行运算,改变内部数据,同时返回参与计算的对象本身,方便下一次引用计算。

      关键代码:对象内部运算改变结果,返回对象引用本身。

      Mybatis和hibernates如果要用Example直接生成一条SQL语句,中间肯定会使用createCriteria()和andNotEqualTo()之类的函数,前者还有类似于把不同criteria的条件进行并集(or())或交集(and(),createCriteria())操作;后者还可以是andIn()之类的子条件,组合在一起,成为一个criteria。

      比如说使用tk.mybatis里面的包,建立查询语句:new Example(Student.class).createCriteria().andEqualTo("studentId",3303).andIn("classId",{2,4,40}).or().andEqualTo("name","funcfans"),这里实际上可以分成以下几条语句:

      Example example = new Example(Student.class);

      example.createCriteria().andEqualTo("studentId",3303).andIn("classId",{2,4,40});

      example.or().andEqualTo("name","funcfans")

      组合成这样的SQL语句:select * from student where (studentId=3303 and classId in (2,4,40) ) or (name='funcfans')

      这里就可以看出来,这个条件语句的拼接,或者说对数据的过滤流,就属于上面说的过滤器模式。example传入criteria过滤数据流,criteria传入各种数据和条件过滤数据流。(主要解决

      这里摘取部分Example代码:

      1 package tk.mybatis.mapper.entity;
      2 
      3 import org.apache.ibatis.reflection.MetaObject;
      4 import org.apache.ibatis.reflection.SystemMetaObject;
      5 import org.apache.ibatis.type.TypeHandler;
      6 import tk.mybatis.mapper.MapperException;
      7 import tk.mybatis.mapper.mapperhelper.EntityHelper;
      8 import tk.mybatis.mapper.util.Sqls;
      9 import tk.mybatis.mapper.util.StringUtil;
     10 
     11 import java.util.*;
     12 
     13 /**
     14  * 通用的Example查询对象
     15  *
     16  * @author liuzh
     17  */
     18 public class Example implements IDynamicTableName {
     19     protected String orderByClause;
     20 
     21     protected boolean distinct;
     22 
     23     protected boolean exists;
     24 
     25     protected boolean notNull;
     26 
     27     protected boolean forUpdate;
     28 
     29     //查询字段
     30     protected Set<String> selectColumns;
     31 
     32     //排除的查询字段
     33     protected Set<String> excludeColumns;
     34 
     35     protected String countColumn;
     36 
     37     protected List<Criteria> oredCriteria;
     38 
     39     protected Class<?> entityClass;
     40 
     41     protected EntityTable table;
     42     //属性和列对应
     43     protected Map<String, EntityColumn> propertyMap;
     44     //动态表名
     45     protected String tableName;
     46 
     47     protected OrderBy ORDERBY;
     48 
     49     /**
     50      * 默认exists为true
     51      *
     52      * @param entityClass
     53      */
     54     public Example(Class<?> entityClass) {
     55         this(entityClass, true);
     56     }
     57 
     58     /**
     59      * 带exists参数的构造方法,默认notNull为false,允许为空
     60      *
     61      * @param entityClass
     62      * @param exists      - true时,如果字段不存在就抛出异常,false时,如果不存在就不使用该字段的条件
     63      */
     64     public Example(Class<?> entityClass, boolean exists) {
     65         this(entityClass, exists, false);
     66     }
     67 
     68     /**
     69      * 带exists参数的构造方法
     70      *
     71      * @param entityClass
     72      * @param exists      - true时,如果字段不存在就抛出异常,false时,如果不存在就不使用该字段的条件
     73      * @param notNull     - true时,如果值为空,就会抛出异常,false时,如果为空就不使用该字段的条件
     74      */
     75     public Example(Class<?> entityClass, boolean exists, boolean notNull) {
     76         this.exists = exists;
     77         this.notNull = notNull;
     78         oredCriteria = new ArrayList<Criteria>();
     79         this.entityClass = entityClass;
     80         table = EntityHelper.getEntityTable(entityClass);
     81         propertyMap = table.getPropertyMap();
     82         this.ORDERBY = new OrderBy(this, propertyMap);
     83     }
     84 
     85     public Criteria or() {
     86         Criteria criteria = createCriteriaInternal();
     87         criteria.setAndOr("or");
     88         oredCriteria.add(criteria);
     89         return criteria;
     90     }
     91 
     92     public Criteria createCriteria() {
     93         Criteria criteria = createCriteriaInternal();
     94         if (oredCriteria.size() == 0) {
     95             criteria.setAndOr("and");
     96             oredCriteria.add(criteria);
     97         }
     98         return criteria;
     99     }
    100 
    101     protected Criteria createCriteriaInternal() {
    102         Criteria criteria = new Criteria(propertyMap, exists, notNull);
    103         return criteria;
    104     }
    105 
    106 }
    View Code

       以及部分Criteria代码:

      1     protected abstract static class GeneratedCriteria {
      2         protected List<Criterion> criteria;
      3         //字段是否必须存在
      4         protected boolean exists;
      5         //值是否不能为空
      6         protected boolean notNull;
      7         //连接条件
      8         protected String andOr;
      9         //属性和列对应
     10         protected Map<String, EntityColumn> propertyMap;
     11 
     12         protected GeneratedCriteria(Map<String, EntityColumn> propertyMap, boolean exists, boolean notNull) {
     13             super();
     14             this.exists = exists;
     15             this.notNull = notNull;
     16             criteria = new ArrayList<Criterion>();
     17             this.propertyMap = propertyMap;
     18         }
     19 
     20         protected void addCriterion(String condition) {
     21             if (condition == null) {
     22                 throw new MapperException("Value for condition cannot be null");
     23             }
     24             if (condition.startsWith("null")) {
     25                 return;
     26             }
     27             criteria.add(new Criterion(condition));
     28         }
     29 
     30         protected void addCriterion(String condition, Object value, String property) {
     31             if (value == null) {
     32                 if (notNull) {
     33                     throw new MapperException("Value for " + property + " cannot be null");
     34                 } else {
     35                     return;
     36                 }
     37             }
     38             if (property == null) {
     39                 return;
     40             }
     41             criteria.add(new Criterion(condition, value));
     42         }
     43 
     44         protected void addCriterion(String condition, Object value1, Object value2, String property) {
     45             if (value1 == null || value2 == null) {
     46                 if (notNull) {
     47                     throw new MapperException("Between values for " + property + " cannot be null");
     48                 } else {
     49                     return;
     50                 }
     51             }
     52             if (property == null) {
     53                 return;
     54             }
     55             criteria.add(new Criterion(condition, value1, value2));
     56         }
     57 
     58         protected void addOrCriterion(String condition) {
     59             if (condition == null) {
     60                 throw new MapperException("Value for condition cannot be null");
     61             }
     62             if (condition.startsWith("null")) {
     63                 return;
     64             }
     65             criteria.add(new Criterion(condition, true));
     66         }
     67 
     68         protected void addOrCriterion(String condition, Object value, String property) {
     69             if (value == null) {
     70                 if (notNull) {
     71                     throw new MapperException("Value for " + property + " cannot be null");
     72                 } else {
     73                     return;
     74                 }
     75             }
     76             if (property == null) {
     77                 return;
     78             }
     79             criteria.add(new Criterion(condition, value, true));
     80         }
     81 
     82         protected void addOrCriterion(String condition, Object value1, Object value2, String property) {
     83             if (value1 == null || value2 == null) {
     84                 if (notNull) {
     85                     throw new MapperException("Between values for " + property + " cannot be null");
     86                 } else {
     87                     return;
     88                 }
     89             }
     90             if (property == null) {
     91                 return;
     92             }
     93             criteria.add(new Criterion(condition, value1, value2, true));
     94         }
     95 
     96         public Criteria andIsNull(String property) {
     97             addCriterion(column(property) + " is null");
     98             return (Criteria) this;
     99         }
    100 
    101         public Criteria andIsNotNull(String property) {
    102             addCriterion(column(property) + " is not null");
    103             return (Criteria) this;
    104         }
    105 
    106         public Criteria andEqualTo(String property, Object value) {
    107             addCriterion(column(property) + " =", value, property(property));
    108             return (Criteria) this;
    109         }
    110 
    111         public Criteria andNotEqualTo(String property, Object value) {
    112             addCriterion(column(property) + " <>", value, property(property));
    113             return (Criteria) this;
    114         }
    115 
    116         public Criteria andGreaterThan(String property, Object value) {
    117             addCriterion(column(property) + " >", value, property(property));
    118             return (Criteria) this;
    119         }
    120 
    121         public Criteria andGreaterThanOrEqualTo(String property, Object value) {
    122             addCriterion(column(property) + " >=", value, property(property));
    123             return (Criteria) this;
    124         }
    125 
    126         public Criteria andLessThan(String property, Object value) {
    127             addCriterion(column(property) + " <", value, property(property));
    128             return (Criteria) this;
    129         }
    130 
    131         public Criteria andLessThanOrEqualTo(String property, Object value) {
    132             addCriterion(column(property) + " <=", value, property(property));
    133             return (Criteria) this;
    134         }
    135 
    136         public Criteria andIn(String property, Iterable values) {
    137             addCriterion(column(property) + " in", values, property(property));
    138             return (Criteria) this;
    139         }
    140 
    141         public Criteria andNotIn(String property, Iterable values) {
    142             addCriterion(column(property) + " not in", values, property(property));
    143             return (Criteria) this;
    144         }
    145 
    146         public Criteria andBetween(String property, Object value1, Object value2) {
    147             addCriterion(column(property) + " between", value1, value2, property(property));
    148             return (Criteria) this;
    149         }
    150 
    151         public Criteria andNotBetween(String property, Object value1, Object value2) {
    152             addCriterion(column(property) + " not between", value1, value2, property(property));
    153             return (Criteria) this;
    154         }
    155 
    156         public Criteria andLike(String property, String value) {
    157             addCriterion(column(property) + "  like", value, property(property));
    158             return (Criteria) this;
    159         }
    160 
    161         public Criteria andNotLike(String property, String value) {
    162             addCriterion(column(property) + "  not like", value, property(property));
    163             return (Criteria) this;
    164         }
    165 
    166         /**
    167          * 手写条件
    168          *
    169          * @param condition 例如 "length(countryname)<5"
    170          * @return
    171          */
    172         public Criteria andCondition(String condition) {
    173             addCriterion(condition);
    174             return (Criteria) this;
    175         }
    176 
    177         /**
    178          * 手写左边条件,右边用value值
    179          *
    180          * @param condition 例如 "length(countryname)="
    181          * @param value     例如 5
    182          * @return
    183          */
    184         public Criteria andCondition(String condition, Object value) {
    185             criteria.add(new Criterion(condition, value));
    186             return (Criteria) this;
    187         }
    188 
    189         /**
    190          * 手写左边条件,右边用value值
    191          *
    192          * @param condition   例如 "length(countryname)="
    193          * @param value       例如 5
    194          * @param typeHandler 类型处理
    195          * @return
    196          * @deprecated 由于typeHandler起不到作用,该方法会在4.x版本去掉
    197          */
    198         @Deprecated
    199         public Criteria andCondition(String condition, Object value, String typeHandler) {
    200             criteria.add(new Criterion(condition, value, typeHandler));
    201             return (Criteria) this;
    202         }
    203 
    204         /**
    205          * 手写左边条件,右边用value值
    206          *
    207          * @param condition   例如 "length(countryname)="
    208          * @param value       例如 5
    209          * @param typeHandler 类型处理
    210          * @return
    211          * @deprecated 由于typeHandler起不到作用,该方法会在4.x版本去掉
    212          */
    213         @Deprecated
    214         public Criteria andCondition(String condition, Object value, Class<? extends TypeHandler> typeHandler) {
    215             criteria.add(new Criterion(condition, value, typeHandler.getCanonicalName()));
    216             return (Criteria) this;
    217         }
    218 
    219         /**
    220          * 将此对象的不为空的字段参数作为相等查询条件
    221          *
    222          * @param param 参数对象
    223          * @author Bob {@link}0haizhu0@gmail.com
    224          * @Date 2015年7月17日 下午12:48:08
    225          */
    226         public Criteria andEqualTo(Object param) {
    227             MetaObject metaObject = SystemMetaObject.forObject(param);
    228             String[] properties = metaObject.getGetterNames();
    229             for (String property : properties) {
    230                 //属性和列对应Map中有此属性
    231                 if (propertyMap.get(property) != null) {
    232                     Object value = metaObject.getValue(property);
    233                     //属性值不为空
    234                     if (value != null) {
    235                         andEqualTo(property, value);
    236                     }
    237                 }
    238             }
    239             return (Criteria) this;
    240         }
    241 
    242         /**
    243          * 将此对象的所有字段参数作为相等查询条件,如果字段为 null,则为 is null
    244          *
    245          * @param param 参数对象
    246          */
    247         public Criteria andAllEqualTo(Object param) {
    248             MetaObject metaObject = SystemMetaObject.forObject(param);
    249             String[] properties = metaObject.getGetterNames();
    250             for (String property : properties) {
    251                 //属性和列对应Map中有此属性
    252                 if (propertyMap.get(property) != null) {
    253                     Object value = metaObject.getValue(property);
    254                     //属性值不为空
    255                     if (value != null) {
    256                         andEqualTo(property, value);
    257                     } else {
    258                         andIsNull(property);
    259                     }
    260                 }
    261             }
    262             return (Criteria) this;
    263         }
    264 
    265         public Criteria orIsNull(String property) {
    266             addOrCriterion(column(property) + " is null");
    267             return (Criteria) this;
    268         }
    269 
    270         public Criteria orIsNotNull(String property) {
    271             addOrCriterion(column(property) + " is not null");
    272             return (Criteria) this;
    273         }
    274 
    275         public Criteria orEqualTo(String property, Object value) {
    276             addOrCriterion(column(property) + " =", value, property(property));
    277             return (Criteria) this;
    278         }
    279 
    280         public Criteria orNotEqualTo(String property, Object value) {
    281             addOrCriterion(column(property) + " <>", value, property(property));
    282             return (Criteria) this;
    283         }
    284 
    285         public Criteria orGreaterThan(String property, Object value) {
    286             addOrCriterion(column(property) + " >", value, property(property));
    287             return (Criteria) this;
    288         }
    289 
    290         public Criteria orGreaterThanOrEqualTo(String property, Object value) {
    291             addOrCriterion(column(property) + " >=", value, property(property));
    292             return (Criteria) this;
    293         }
    294 
    295         public Criteria orLessThan(String property, Object value) {
    296             addOrCriterion(column(property) + " <", value, property(property));
    297             return (Criteria) this;
    298         }
    299 
    300         public Criteria orLessThanOrEqualTo(String property, Object value) {
    301             addOrCriterion(column(property) + " <=", value, property(property));
    302             return (Criteria) this;
    303         }
    304 
    305         public Criteria orIn(String property, Iterable values) {
    306             addOrCriterion(column(property) + " in", values, property(property));
    307             return (Criteria) this;
    308         }
    309 
    310         public Criteria orNotIn(String property, Iterable values) {
    311             addOrCriterion(column(property) + " not in", values, property(property));
    312             return (Criteria) this;
    313         }
    314 
    315         public Criteria orBetween(String property, Object value1, Object value2) {
    316             addOrCriterion(column(property) + " between", value1, value2, property(property));
    317             return (Criteria) this;
    318         }
    319 
    320         public Criteria orNotBetween(String property, Object value1, Object value2) {
    321             addOrCriterion(column(property) + " not between", value1, value2, property(property));
    322             return (Criteria) this;
    323         }
    324 
    325         public Criteria orLike(String property, String value) {
    326             addOrCriterion(column(property) + "  like", value, property(property));
    327             return (Criteria) this;
    328         }
    329 
    330         public Criteria orNotLike(String property, String value) {
    331             addOrCriterion(column(property) + "  not like", value, property(property));
    332             return (Criteria) this;
    333         }
    334 
    335         /**
    336          * 手写条件
    337          *
    338          * @param condition 例如 "length(countryname)<5"
    339          * @return
    340          */
    341         public Criteria orCondition(String condition) {
    342             addOrCriterion(condition);
    343             return (Criteria) this;
    344         }
    345 
    346         /**
    347          * 手写左边条件,右边用value值
    348          *
    349          * @param condition 例如 "length(countryname)="
    350          * @param value     例如 5
    351          * @return
    352          */
    353         public Criteria orCondition(String condition, Object value) {
    354             criteria.add(new Criterion(condition, value, true));
    355             return (Criteria) this;
    356         }
    357 
    358         /**
    359          * 将此对象的不为空的字段参数作为相等查询条件
    360          *
    361          * @param param 参数对象
    362          * @author Bob {@link}0haizhu0@gmail.com
    363          * @Date 2015年7月17日 下午12:48:08
    364          */
    365         public Criteria orEqualTo(Object param) {
    366             MetaObject metaObject = SystemMetaObject.forObject(param);
    367             String[] properties = metaObject.getGetterNames();
    368             for (String property : properties) {
    369                 //属性和列对应Map中有此属性
    370                 if (propertyMap.get(property) != null) {
    371                     Object value = metaObject.getValue(property);
    372                     //属性值不为空
    373                     if (value != null) {
    374                         orEqualTo(property, value);
    375                     }
    376                 }
    377             }
    378             return (Criteria) this;
    379         }
    380 
    381         /**
    382          * 将此对象的所有字段参数作为相等查询条件,如果字段为 null,则为 is null
    383          *
    384          * @param param 参数对象
    385          */
    386         public Criteria orAllEqualTo(Object param) {
    387             MetaObject metaObject = SystemMetaObject.forObject(param);
    388             String[] properties = metaObject.getGetterNames();
    389             for (String property : properties) {
    390                 //属性和列对应Map中有此属性
    391                 if (propertyMap.get(property) != null) {
    392                     Object value = metaObject.getValue(property);
    393                     //属性值不为空
    394                     if (value != null) {
    395                         orEqualTo(property, value);
    396                     } else {
    397                         orIsNull(property);
    398                     }
    399                 }
    400             }
    401             return (Criteria) this;
    402         }
    403 
    404         public List<Criterion> getAllCriteria() {
    405             return criteria;
    406         }
    407 
    408         public String getAndOr() {
    409             return andOr;
    410         }
    411 
    412         public void setAndOr(String andOr) {
    413             this.andOr = andOr;
    414         }
    415 
    416         public List<Criterion> getCriteria() {
    417             return criteria;
    418         }
    419 
    420         public boolean isValid() {
    421             return criteria.size() > 0;
    422         }
    423     }
    424 
    425     public static class Criteria extends GeneratedCriteria {
    426 
    427         protected Criteria(Map<String, EntityColumn> propertyMap, boolean exists, boolean notNull) {
    428             super(propertyMap, exists, notNull);
    429         }
    430     }
    View Code

      这些代码,都是在内部运算数据然后返回引用本身(如何解决),使得方法可以像做数学公式一样进行运算,过滤(或者说改变)数据流,Spark的RDD就是受了这个设计模式的启发,在action触发之前,运行的函数本身不会对数据流运算,不过内部会标记数据流需要进行的运算,这也是标准模式的运用。

    图1.像不像标准模式的过滤数据流?

  • 相关阅读:
    25.Zabbix入门必备
    6.Ansible Roles角色实战
    5.Ansible Jinja2 模板
    4.Ansible Task控制
    3.Ansible varialbes实战
    2.Ansible Playbook剧本
    1.Ansible自动化管理工具
    网站架构面试题必备
    winsows CMD及Linux命令大全 欢迎补充
    Oracle查询表空间
  • 原文地址:https://www.cnblogs.com/dgutfly/p/11616498.html
Copyright © 2011-2022 走看看