APIJSON 博客5 AbstractSQLConfig 第五篇

本文详细分析了APIJSON中AbstractSQLConfig的getEqualString(), getCompareString(), getKey()和getSQLKey()方法,探讨了SQL中的Equal()函数、PreparedStatement的预编译优势以及方法重载的概念。还介绍了PostgreSQL的特性,如函数、索引、触发器、多版本并发控制等。" 116555604,10537922,Linux内核子系统详解:系统调用、进程管理、内存管理等,"['Linux内核', '操作系统', '进程调度', '内存管理', '文件系统']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值