首页 > 其他分享 >oql4j对象查询语言

oql4j对象查询语言

时间:2024-09-11 09:13:43浏览次数:1  
标签:null 转换 name 对象 arg1 参数 字符串 查询语言 oql4j

一、简介

1.1 介绍

oql4j 全称 Object Query Language For Java,即java版本的对象查询语言,支持使用编写查询语言快速的搜索出符合条件的对象,简化对象的过滤处理操作。
目前支持where条件的过滤和select的映射查询,后续将支持update更新等操作。

二、使用指南

2.1 依赖说明

  • 基于jdk8版本
  • 依赖antlr4包(pom依赖自动引入)
  • 依赖commons-beanutils包(pom依赖自动引入)

2.2 使用主代码

OqlClientBuilder oqlClientBuilder = new OqlClientBuilder();
OqlClient oqlClient = oqlClientBuilder.build();

然后就可以使用oqlClient对象,进行各种where条件的操作,select的映射查询,例如操作oqlClient.doWhereFilter(...)、oqlClient.doSelect(...)

OqlClient接口的默认实现类是DefaultOqlClientImpl,此类是线程安全的,所以oqlClient对象可作为单例在整个项目中使用

2.3 Where条件使用案例的demo

OqlClientBuilder oqlClientBuilder = new OqlClientBuilder();
OqlClient oqlClient = oqlClientBuilder.build();
// 原数据
Map<String, String> srcMap = new HashMap<>();
srcMap.put("name", "李明");
// 编写oql语法
String whereOqlExp = " ${name} is not null ";
// name字段不为空,判断是否存在这样的原数据。
boolean result = oqlClient.doWhereExists(whereOqlExp, srcMap);
// 打印的结果为true
System.out.println(result);

更多的使用demo,可参考代码的测试用例:com.cat.oqj4j.core.OqlClientlWhereTest

2.4 Select映射使用案例的demo

OqlClientBuilder oqlClientBuilder = new OqlClientBuilder();
OqlClient oqlClient = oqlClientBuilder.build();
// 原数据
PersonTest p01 = new PersonTest();
p01.setName("张三");
p01.setIsMan(true);
p01.setAge(36);
// 编写oql语法
String selectOqlExp = " ${age} myAge, ${isMan} as knownGender, ${name} as myName, ${addr.province} as  myAddr.province,  ${addr.city} myAddr.city";
// 执行select映射,将映射结果赋值到MyPersonTest对象。
MyPersonTest result = oqlClient.doSelect(selectOqlExp, p01, MyPersonTest.class);

更多的使用demo,可参考代码的测试用例:com.cat.oqj4j.core.OqlClientlSelectTest

三、语法规则

3.1 语法基础

3.1.1 基本类型说明:

类型 类型demo
字符串 有单双引号的内容都是属于字符串,例如 "name"、'name' 表示常量name
数值 数字类的都属于数值类型,包括整数和小数以及科学计数法,例如99、9993.66、-321、 1e3
布尔 布尔值类型,只有真和假,并且不区分大小写,例如true、True、TRUE、false、False、FALSE
null null类型,并且不区分大小写,例如null、Null、NULL

3.1.2 语法概览:

关键字 说明 语法demo 详细说明
${} 取值操作 ${name} 表示取对象的name属性 3.1.2.1 取值操作
F{} 执行函数 F{StrLen(${name})} 表示取出对象的name属性值并且执行StrLen函数 3.1.2.2 执行函数

3.1.2.1 取值操作

  • 使用${}来表示,例如${name} 表示取对象的name属性值,支持嵌套取值,使用.来分割,
    例如${addr.city}表示取对象的addr属性下的city属性,即取出addr属性后,再操作addr对象取出city属性。


  • 注意嵌套取值时,如果上层属性必为null,则直接返回null值,例如嵌套取city属性时,city的上层属性addr为null,则取到的city属性也为null。


  • 取值操作是基本语法,支持在select映射语法、where条件语法中使用。

3.1.2.2 执行函数

  • 用于执行预定义和自定义的函数,使用F{}关键字,关键字不区分大小写, F{}、f{} 都能识别。


  • 格式为F{funName}、F{funName()}、F{funName(arg1,arg2...)} 均支持,默认都会传操作集合的原对象和遍历的当前对象这两个参数,
    有需要的可以额外追加参数,并且追加的参数可以为常量参数也可以为动态取值参数。
    例如: F{StrLen(${name})} 表示取出对象的name属性值作为参数,执行StrLen函数。
    例如: F{CastInt(F{StrLen(${age})})} > 2 表示取出对象的age属性值,取得字符串长度,然后再转换为int类型,并对函数结果进行大于2判断。


  • 取值操作是基本语法,支持在select映射语法、where条件语法中使用。
    例如在select映射语法的使用: F{IfNull(${name}, '未知')}
    例如在where条件语法的使用: F{StrLen(${name})} > 2


  • 框架预定义的函数如下(支持自定义函数,具体可查看 5.1 自定义函数):

    函数名 功能 所需参数 详细说明
    StrLen 字符串长度 StrLen(arg1),arg1:用于判断字符串长度的参数 将传入的参数转换为字符串,统计并返回字符串长度。如果参数为null,则返回长度为0。
    If 三元表达式条件处理 If(arg1,arg2,arg3),arg1:用于判断条件的真假,arg2:条件为真时的返回值,arg3:条件为假时的返回值 用于判断arg1参数,如果为真则返回arg2参数,反之返回arg3。数值0和false字符串都属于假,1和true字符串则属于真(false和true字符串不区分大小写)。
    IfNull null结果时取默认值 IfNull(arg1,arg2),arg1:主参数值,arg2:默认值 如果arg1参数不为null则返回此值,否则返回arg2参数。
    CastStr 转换为字符串 CastStr(arg1),arg1:用于转换为字符串的参数 将传入的参数转换为字符串,如果参数为null,则返回null。
    CastBigDec 转换为BigDecimal CastBigDec(arg1),arg1:用于转换为BigDecimal的参数 将传入的参数转换为BigDecimal,如果参数为null,则返回null。
    CastInt 转换为Integer CastInt(arg1),arg1:用于转换为Integer的参数 将传入的参数转换为Integer,如果参数为null,则返回null。
    CastLong 转换为Long CastLong(arg1),arg1:用于转换为Long的参数 将传入的参数转换为Long,如果参数为null,则返回null。
    CastByte 转换为Byte CastByte(arg1),arg1:用于转换为Byte的参数 将传入的参数转换为Byte,如果参数为null,则返回null。
    CastFloat 转换为Float CastFloat(arg1),arg1:用于转换为Float的参数 将传入的参数转换为Float,如果参数为null,则返回null。
    CastDouble 转换为Double CastDouble(arg1),arg1:用于转换为Double的参数 将传入的参数转换为Double,如果参数为null,则返回null。
    CastChar 转换为Character CastChar(arg1),arg1:用于转换为Character的参数 将传入的参数转换为Character,如果参数为null或者为""字符串,则返回null,长度大于1则转换报错。
    CastBool 转换为Boolean CastBool(arg1),arg1:用于转换为Boolean的参数 将传入的参数转换为Boolean,如果参数为null,则返回null。数值0和false字符串都属于假,1和true字符串则属于真(false和true字符串不区分大小写)。
    ClassSimpleName 获取Class简短名称 ClassSimpleName(arg1),arg1:用于获取Class字节码对象的简短名称的参数 将传入的参数去除Class字节码对象并获取简短名称,如果参数为null,则返回"null"字符串。
    NotExistNull 判断全部参数都不为null NotExistNull(arg1,arg2,arg3...),需要判断的参数,不限制参数数量 将传入的参数逐一判断,如果都不为null则返回true,反之false。如果没有传入任何参数,则返回true。
  • 框架预定义的函数使用demo,可参考代码的测试用例:com.cat.oqj4j.core.OqlClientFunTest

3.2 Where条件语法

3.2.1 语法概览:

关键字 说明 语法demo 详细说明
and 并且条件 ${name} = '张三' and ${age} > 20 表示名称为张三并年龄大于20 3.2.1.1 并且条件
or 或者条件 ${name} = '张三' or ${name} = '李四' 表示名称为张三或者李四 3.2.1.2 或者条件
() 括号运算 (${name} = '张三' or ${name} = '李四') and ${age} > 20 表示先判断名称可为张三或者李四,然后再判断年龄大于20岁 3.2.1.3 括号运算
in 同时指定多个或者条件 ${name} in ('张三','李四') 表示名称为张三或者李四 3.2.1.4 同时指定多个或者条件
between 范围条件 ${age} between 20 and 30 表示年龄在[20,30]范围内 3.2.1.5 范围条件
is null 等于空 ${name} is null 表示姓名为null 等价于 ${name} = null 3.2.1.6 等于空
is not null 不等于空 ${name} is not null 表示姓名不为null 等价于 ${name} != null 3.2.1.7 不等于空

3.2.1.1 并且条件

  • 对多个条件进行交集处理,and关键字不区分大小写,即and、And、AND 都能识别。
  • 支持用 && 代替and关键字。例如:${name} = '张三' and ${age} > 20 等价于 ${name} = '张三' && ${age} > 20
  • and的优先级比or要高。

3.2.1.2 或者条件

  • 对多个条件进行并集处理,or关键字不区分大小写,即or、Or、OR 都能识别。
  • 支持用 || 代替or关键字。例如:${name} = '张三' or ${age} > 20 等价于 ${name} = '张三' || ${age} > 20
  • or的优先级小于and。

3.2.1.3 括号运算

  • 用于提升运算优先级,使用()将表达式括起来,括号内的表达式将优先执行,常用于在and、or条件下进行配套使用。
  • 括号表达式的运算优先级比and、or都高

3.2.1.4 同时指定多个或者条件

  • 当存在or参数时,可以使用in关键字来实现,关键字不区分大小写,即in、In、IN都能识别。
  • 格式为 keyName in (arg1,arg2,arg3,arg4...),arg参数可以是常量参数,也可以是动态取值参数,
    例如 ${name} in ('李白', ${formerName}) 表示判断对象的name属性值是否为 李白 或者为此对象的formerName属性。
  • in内的arg参数不限制数量,并且可以同时为各种类型数据,例如可以同时有字符串类型、数值类型等。

3.2.1.5 范围条件

  • 当需要判断范围时,可以使用between关键字,关键字不区分大小写,即between、Between、BETWEEN等都能识别。
  • 格式为keyName between arg1 and arg2、keyName between arg1 && arg2, 大于等于arg1 并且小于等于 arg2,等价于 >=arg1 and <=arg2。
    例如 ${age} between 20 and 30 表示年龄在[20,30]范围内,20、21、29、30等均符合,用&&写法则为${age} between 20 && 30

3.2.1.6 等于空

  • 用于判断值是否为null,使用 is null 关键字,关键字不区分大小写, is、IS、null、Null、NULL等都能识别。
  • 格式为 keyName is null, 例如 ${name} is null 表示name属性值为null的判断,也等价于 ${name} = null 表达式。

3.2.1.7 不等于空

  • 用于判断值是否不为null,使用 is not null 关键字,关键字不区分大小写, is、IS、not、Not、null、Null、NULL等都能识别。
  • 格式为 keyName is not null, 例如 ${name} is not null 表示name属性值不为null的判断,也等价于 ${name} != null 表达式。

3.2.2 其他说明:

  • where条件支持使用比较符合,具体符合和比较规则,详见 4.1 比较说明
  • 当使用单指作为条件时,必须是布尔类型,或者是可以转换为布尔类型的数字或字符串,否则语法执行将报错。布尔类型转换详见4.2 布尔类型的转换

3.3 Select映射语法

3.3.1 使用格式:

  • 直接写需要映射的字段,字段间使用英文逗号分隔,例如: name1, name2, name3, name4 ...

3.3.1 指定映射别名:

  • 默认不指定的情况下,则直接用原字段名称,例如: ${name1}, ${name2} 表示取原对象的name1和name2属性,并映射赋值到目标对象的name1和name2属性。


    如果是使用${}动态取值,默认情况下映射到目标对象的名称为取值字段名,例如${name} 表示取原对象的name属性,并映射赋值到目标对象的name属性。


    如果是F{}函数,默认情况下映射到目标对象的名称为函数名,例如F{ClassSimpleName(${name})} 表示取原对象的name属性,并执行ClassSimpleName函数后,将结果映射赋值到目标对象的ClassSimpleName属性。


  • 使用空格方式指定。例如:${name1} fatherName, ${name2} motherName 表示取原对象的name1和name2属性,并映射赋值到目标对象的fatherName和motherName属性。


  • 使用AS关键字指定,并且as关键字不区分大小写。例如:${name1} AS fatherName, ${name2} as motherName 表示取原对象的name1和name2属性,并映射赋值到目标对象的fatherName和motherName属性。


四、约定说明

4.1 比较说明

  • 目前支持的比较符号如下

    符号 含义
    > 大于
    < 小于
    = 等于
    >= 大于等于
    <= 小于等于
    != 不等于
    <> 不等于
  • 支持不同类型进行比较,规则如下:

    1. 判断相等时:如果是相同类型,判断相等时直接调用对象的equalse方法比较。
    2. 判断相等时:如果比较对象有null,则要求另外个对象也必须为null才相等,否则均为不等。
    3. 判断相等时:如果比较对象有个为布尔类型,另外个对象为字符串或数字时,则尝试统一转换为布尔值进行比较。0和false字符串都属于假,1和true字符串则属于真(false和true字符串不区分大小写)。
    4. 判断相等时:如果都是同属于Number子类,则转换为浮点型比较。
    5. 判断相等时:如果都是属于其中一种(java原始类型、字符串类型、Number子类),统一获取对象字符串进行比较。
    6. 判断大小时:如果存在有对象为null,属于无法比较大小,均返回false。
    7. 判断大小时:如果对象均为BigDecimal,转为BigDecimal进行比较
    8. 判断大小时:如果都是同属于Number子类,则转换为浮点型比较。
    9. 判断大小时:如果存在有对象为布尔值,属于无法比较大小,均返回false。
    10. 判断大小时:如果都是属于其中一种(java原始类型、字符串类型、Number子类),统一获取对象字符串进行比较(先比较长度,然后在比较asscii码值)。

4.2 布尔类型的转换

  • 支持原生的布尔类型
  • 如果是数字类型(Number子类),0属于假可以转换为false布尔值,1属于真可以转换为true布尔值。
  • 如果是字符串类型,"false"、'false'字符串属于假可以转换为false布尔值,"true"、'true'字符串属于真可以转换为true布尔值,并且字符串不区分大小写。

4.3 关键字大小写

除特殊情况外,默认情况下,关键字是不区分大小写的,均能识别,可根据需要自行选择使用。例如 And、AND、and、As、AS、as 等关键字都能识别。

4.4 线程安全

凡是对应的接口或者类名上有com.cat.oqj4j.annotation.ThreadSafe注解的,均表示此接口实现类和指定类都是线程安全的,生成的对象可作为单例使用。

五、高阶应用

5.1 自定义函数

  • 除了使用框架预定义的函数以外,还支持自定义函数,方式如下:
    1. 实现com.cat.oqj4j.antlr.handler.FunHandler接口,或者继承com.cat.oqj4j.antlr.handler.AbstractFunHandler类。注意实现类必须是线程安全的。
    2. 注册函数,在OqlClientBuilder构造时注册,然后在表达式中通过F{}即可使用。
    OqlClientBuilder oqlClientBuilder = new OqlClientBuilder();
    // MyFunHandler是你自定义的函数类,根据需要更改类名。注意MyFunHandler是满足线程安全的。
    oqlClientBuilder.registerFunHandler(new MyFunHandler());

5.2 自定义bean操作

  • 对bean的设值和赋值的操作,目前框架使用的是ApacheUtilsBeanHandler,此类是基于apache的commons-beanutils工具包的PropertyUtils类来实现,如果需要者可以自定义bean操作类,方式如下:
    1. 实现com.cat.oqj4j.support.BeanHandler接口。注意实现类必须是线程安全的。
    2. 设置bean操作器,在OqlClientBuilder构造时设置,后续对bean的操作都会自动用此操作器。
    OqlClientBuilder oqlClientBuilder = new OqlClientBuilder();
    // MyBeanHandler是你实现的bean操作器,根据需要更改类名。注意MyBeanHandler是满足线程安全的。
    oqlClientBuilder.setBeanHandler(new MyBeanHandler());

附加

源码将发布在github上进行管理,同时在gittee进行放开查看。


作者联系方式:

标签:null,转换,name,对象,arg1,参数,字符串,查询语言,oql4j
From: https://www.cnblogs.com/catgwj/p/18407637

相关文章

  • 面向对象编程(OOP)之深入理解
    前言:想象一下,你正在搭建一座乐高城堡。你不需要从头开始制作每一个砖块,而是利用现成的砖块,按照说明书进行组装。面向对象编程(OOP)也是类似的理念,它将复杂的程序分解成一个个独立的“砖块”——对象,然后通过组合这些对象来构建整个程序。1.封装:保护数据,控制访问就像乐高城......
  • 章10——面向对象编程(高级部分)——内部类
    重点掌握匿名内部类的使用!1、内部类可以随意访问外部类的成员,包括私有的属性,而外部类不可以。2、内外部类有重名属性时,内部类的访问采用就近原则,如想访问外部的成员,则用外部类名.this.属性名。内部类分类,四种局部内部类第七条解释:Outer02.this本质是一个外部类的对象。......
  • C++入门基础知识60——【关于C++ 类 & 对象】
    成长路上不孤单......
  • Java【类和面向对象】
    Java作为一种面向对象的编程语言,支持类、对象、继承、封装、多态、接口、抽象、方法、方法重载的概念。1.类和对象1.1基本概念1.1.1类(Class)一组相关属性和行为的集合。可以看成是一类事物的模板,用于定义对象的蓝图,包括属性和方法(描述该类事物)。1.1.2对象(Object)一类事物......
  • Java并发编程 第七章 共享模型之不可变对象
    1.不可变对象@Slf4j(topic="c.Test1")publicclassTest1{publicstaticvoidmain(String[]args){SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd");for(inti=0;i<100;i++){newThread(()-......
  • 访谈对象招募|女程序员身份建构与文化认同
    ......
  • JavaScript高级——对象
    1、对象的含义:①多个数据的封装体②用来保存多个数据的容器③一个对象代表现实中的一个事物2、为什么要用对象?——统一管理多个数据3、对象的组成①属性:属性名(字符串)和属性值(任意值)组成。代表现实事物的状态数据。②方法:一种特别的属性(属性值是函数)。代表的现......
  • 【useTranslation】兼容数组解构和对象解构的三种实现方式
    useTranslation使用:数组解构:const[t,i18n]=useTranslation();对象解构:const{t,i18n}=useTranslation();useTranslation兼容数组解构和对象解构的三种实现方式:1.返回带属性的数组在这种实现方式中,返回一个数组,并为该数组添加对象属性。这样可以同时使用数组......
  • js对象转数组对象
    1.创建一个baseFun.jsexportfunctionobjectFun(obj){constresult=[]//处理所有可能的JSON字符串字段,递归处理所有嵌套JSON字符串functionprocessJsonFields(obj){for(constkeyinobj){if(obj.hasOwnProperty(key)){......
  • RapidJSON 的坑--允许Object对象存在相同的key,且key为数字时序列化报异常
    RapidJSON的坑--允许Object对象存在相同的key,且key为数字时序列化报异常测试代码如下:1voidshow(rapidjson::Document&doc)2{3printf("-----------------foriterator\nMemberCount:%d\n",doc.MemberCount());4for(autoit=doc.MemberBegin();it!=doc......