2021SC@SDUSC
继续上周对AbstractSQLConfig的分析
后续代码为对
getEqualString()
getCompareString()
getKey()
getSQLKey()
方法的定义
知识学习
SQL中的Equal() 函数
Equal( ) 函数用于比较两个可变长度的不透明类型。此函数实现比较运算符,因此可以通过使用函数名或对应符号在 SQL 语句中使用。
返回:布尔值
语法
Equal(node1,node2)
node
要测试相等性的节点。
node2
要与第一个节点比较以测试相等性的节点。示例
示例 1
SELECT * FROM tablename WHERE Equal(nodecolumn, “1.4”);示例 2
SELECT * FROM tablename WHERE nodecolumn = “1.4”;此示例与示例 1 相同,不同之处是使用了等号。
在getEqualString() 中添加了错误判断和报错信息
if (JSON.isBooleanOrNumberOrString(value) == false && value instanceof Subquery == false)
throw new IllegalArgumentException(key + ":value 中value不合法!非PUT请求只支持 [Boolean, Number, String] 内的类型 !");
boolean not = key.endsWith("!"); // & | 没有任何意义,写法多了不好控制
if (StringUtil.isName(key) == false)
throw new IllegalArgumentException(key + ":value 中key不合法!不支持 ! 以外的逻辑符 !");
后续几个方法定义类似,不再赘述
我们来看下面的代码
private List<Object> preparedValueList = new ArrayList<>();
private Object getValue(@NotNull Object value) {
if (isPrepared()) {
preparedValueList.add(value);
return "?";
}
return getSQLValue(value);
}
public Object getSQLValue(@NotNull Object value) {
// return (value instanceof Number || value instanceof Boolean) && DATABASE_POSTGRESQL.equals(getDatabase()) ? value : "'" + value + "'";
return (value instanceof Number || value instanceof Boolean) ? value : "'" + value + "'"; //MySQL 隐式转换用不了索引
}
@Override
public List<Object> getPreparedValueList() {
return preparedValueList;
}
@Override
public AbstractSQLConfig setPreparedValueList(List<Object> preparedValueList) {
this.preparedValueList = preparedValueList;
return this;
}
使用prepareStatement预编译,值为 ? ,后续动态set进去
知识学习
prepareStatement 的用法和解释
1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程2.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。
3.statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得, preparedstatement支持批处理Code Fragment 1:
String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE ′Colombian′";
stmt.executeUpdate(updateString);Code Fragment 2:
PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate();片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。
这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。
@JSONField(serialize = false)
public String getSearchString(String key, Object value, String rawSQL) throws IllegalArgumentException {
if (rawSQL != null) {
throw new UnsupportedOperationException("@raw:value 中 " + key + " 不合法!@raw 不支持 key$ 这种功能符 !只支持 key, key!, key<, key{} 等比较运算 和 @column, @having !");
}
if (value == null) {
return "";
}
Logic logic = new Logic(key);
key = logic.getKey();
Log.i(TAG, "getSearchString key = " + key);
JSONArray arr = newJSONArray(value);
if (arr.isEmpty()) {
return "";
}
return getSearchString(key, arr.toArray(), logic.getType());
}
public String getSearchString(String key, Object[] values, int type) throws IllegalArgumentException {
if (values == null || values.length <= 0) {
return "";
}
String condition = "";
for (int i = 0; i < values.length; i++) {
Object v = values[i];
if (v instanceof String == false) {
throw new IllegalArgumentException(key + "$:value 中 value 的类型只能为 String 或 String[]!");
}
if (((String) v).isEmpty()) { // 允许查空格 StringUtil.isEmpty((String) v, true)
throw new IllegalArgumentException(key + "$:value 中 value 值 " + v + "是空字符串,没有意义,不允许这样传!");
}
// if (((String) v).contains("%%")) { // 需要通过 %\%% 来模糊搜索 %
// throw new IllegalArgumentException(key + "$:value 中 value 值 " + v + " 中包含 %% !不允许有连续的 % !");
// }
condition += (i <= 0 ? "" : (Logic.isAnd(type) ? AND : OR)) + getLikeString(key, v);
}
return getCondition(Logic.isNot(type), condition);
}
public String getSearchString(String key, Object value, String rawSQL)
public String getSearchString(String key, Object[] values, int type)
这里是对getSearchString的方法重载,定义了不同的报错类型
知识学习
重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则:
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
后面是对不同输入类型的getRegExpString的报错处理
public String getRegExpString(String key, Object value, boolean ignoreCase, String rawSQL) throws IllegalArgumentException
public String getRegExpString(String key, Object[] values, int type, boolean ignoreCase) throws IllegalArgumentException
@JSONField(serialize = false)
public String getRegExpString(String key, String value, boolean ignoreCase) {
if (isPostgreSQL()) {
return getKey(key) + " ~" + (ignoreCase ? "* " : " ") + getValue(value);
}
if (isOracle()) {
return "regexp_like(" + getKey(key) + ", " + getValue(value) + (ignoreCase ? ", 'i'" : ", 'c'") + ")";
}
if (isClickHouse()) {
return "match(" + (ignoreCase ? "lower(" : "") + getKey(key) + (ignoreCase ? ")" : "") + ", " + (ignoreCase ? "lower(" : "") + getValue(value) + (ignoreCase ? ")" : "") + ")";
}
return getKey(key) + " REGEXP " + (ignoreCase ? "" : "BINARY ") + getValue(value);
}
而getRegExpString方法的定义如上,对不同类型的数据库进行判断后返回不同的语句
分为以下三种
知识学习
PostgreSQL
PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),是以加州大学计算机系开发的POSTGRES,4.2版本为基础的对象关系型数据库管理系统。POSTGRES的许多领先概念只是在比较迟的时候才出现在商业网站数据库中。PostgreSQL支持大部分的SQL标准并且提供了很多其他现代特性,如复杂查询、外键、触发器、视图、事务完整性、多版本并发控制等。同样,PostgreSQL也可以用许多方法扩展,例如通过增加新的数据类型、函数、操作符、聚集函数、索引方法、过程语言等。另外,因为许可证的灵活,任何人都可以以任何目的免费使用、修改和分发PostgreSQL。
PostgreSQL 特征
函数:通过函数,可以在数据库服务器端执行指令程序。
索引:用户可以自定义索引方法,或使用内置的 B 树,哈希表与 GiST 索引。
触发器:触发器是由SQL语句查询所触发的事件。如:一个INSERT语句可能触发一个检查数据完整性的触发器。触发器通常由INSERT或UPDATE语句触发。 多版本并发控制:PostgreSQL使用多版本并发控制(MVCC,Multiversion concurrency control)系统进行并发控制,该系统向每个用户提供了一个数据库的"快照",用户在事务内所作的每个修改,对于其他的用户都不可见,直到该事务成功提交。
规则:规则(RULE)允许一个查询能被重写,通常用来实现对视图(VIEW)的操作,如插入(INSERT)、更新(UPDATE)、删除(DELETE)。
数据类型:包括文本、任意精度的数值数组、JSON 数据、枚举类型、XML 数据
等。全文检索:通过 Tsearch2 或 OpenFTS,8.3版本中内嵌 Tsearch2。
NoSQL:JSON,JSONB,XML,HStore 原生支持,至 NoSQL 数据库的外部数据包装器。
数据仓库:能平滑迁移至同属 PostgreSQL 生态的 GreenPlum,DeepGreen,HAWK 等,使用 FDW 进行 ETL。
Oracle Database
Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小微机环境。它是一种高效率的、可靠性好的、适应高吞吐量的数据库方案。
1、完整的数据管理功能: [1]
1)数据的大量性
2)数据的保存的持久性
3)数据的共享性
4)数据的可靠性
2、完备关系的产品:
1)信息准则---关系型DBMS的所有信息都应在逻辑上用一种方法,即表中的值显式地表示;
2)保证访问的准则
3)视图更新准则---只要形成视图的表中的数据变化了,相应的视图中的数据同时变化
4)数据物理性和逻辑性独立准则
3、分布式处理功能:
ORACLE数据库自第5版起就提供了分布式处理能力,到第7版就有比较完善的分布式数据库功能了,一个ORACLE分布式数据库由oraclerdbms、sql*Net、SQL*CONNECT和其他非ORACLE的关系型产品构成。
4、用ORACLE能轻松的实现数据仓库的操作。
这是一个技术发展的趋势,不在这里讨论。
■ 可用性强
■ 可扩展性强
■ 数据安全性强
■ 稳定性强
ClickHouse
ClickHouse 是一个真正的列式数据库管理系统(DBMS)。在 ClickHouse 中,数据始终是按列存储的,包括矢量(向量或列块)执行的过程。只要有可能,操作都是基于矢量进行分派的,而不是单个的值,这被称为«矢量化查询执行»,它有利于降低实际的数据处理开销。
Clickhouse的具体特点;
1.真正的面向列的DBMS
2.数据高效压缩
3.磁盘存储的数据
4.多核并行处理
5.在多个服务器上分布式处理
6.SQL语法支持
7.向量化引擎
8.实时数据更新
9.索引
10.适合在线查询
11.支持近似预估计算
12.支持嵌套的数据结构
支持数组作为数据类型
13.支持限制查询复杂性以及配额
14.复制数据复制和对数据完整性的支持
2172