2021SC@SDUSC
继续上周对AbstractSQLConfig的分析,后面的代码是@override
@Override
public boolean isExplain() {
return explain;
}
@Override
public AbstractSQLConfig setExplain(boolean explain) {
this.explain = explain;
return this;
}
@Override
public List<Join> getJoinList() {
return joinList;
}
知识学习
@Override是伪代码,表示重写。(当然不写@Override也可以),不过写上有如下好处:
1、可以当注释用,方便阅读;
2、编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错。例如,你如果没写@Override,而你下面的方法名又写错了,这时你的编译器是可以编译通过的,因为编译器以为这个方法是你的子类中自己增加的方法。
举例:在重写父类的onCreate时,在方法前面加上@Override 系统可以帮你检查方法的正确性。
@Override
public void onCreate(Bundle savedInstanceState){…….}
这种写法是正确的,如果你写成:@Override
public void oncreate(Bundle savedInstanceState)
{…….}
编译器会报如下错误:The method oncreate(Bundle) of type HelloWorld must override or implement a supertype method,以确保你正确重写onCreate方法(因为oncreate应该为onCreate)。而如果你不加@Override,则编译器将不会检测出错误,而是会认为你为子类定义了一个新方法:oncreate
这里用到了@JSONField
@JSONField(serialize = false)
public int getOffset() {
return getOffset(getPage(), getCount());
}
/**获取初始位置offset
* @param page
* @param count
* @return
*/
public static int getOffset(int page, int count) {
return page*count;
}
/**获取限制数量
* @return
*/
@JSONField(serialize = false)
public String getLimitString() {
if (count <= 0 || RequestMethod.isHeadMethod(getMethod(), true)) {
return "";
}
return getLimitString(getPage(), getCount(), isOracle() || isSQLServer() || isDb2(), isOracle());
}
public static String getLimitString(int page, int count, boolean isTSQL, boolean isOracle) {
int offset = getOffset(page, count);
if (isTSQL) { // OFFSET FECTH 中所有关键词都不可省略, 另外 Oracle 数据库使用子查询加 where 分页
return isOracle ? " WHERE ROWNUM BETWEEN "+ offset +" AND "+ (offset + count) : " OFFSET " + offset + " ROWS FETCH FIRST " + count + " ROWS ONLY";
}
return " LIMIT " + count + (offset <= 0 ? "" : " OFFSET " + offset); // DELETE, UPDATE 不支持 OFFSET
}
知识学习
FastJson中@JSONField注解使用
json格式在服务器之间进行数据传输。但是json格式数据不符合JAVA中的变量定义规则,并且难以理解,因此需要在后台中做二次处理,将数据处理成我们系统中定义的格式。思路:
1. 定义需要返回的bean,bean中定义需要返回的数据
2. 获取到需要处理的JSON字符串
3. 将JSON字符串转换为bean, 再将转换后的bean返回给客户端。
由于json中的key与bean中的属性不能匹配,因此在转换过程中出现了部分属性为null的情况。经过查看官方文档,发现可以使用@JSONField进行解释,但是并没有详细的使用说明。
@JSONField的作用对象:
1. Field
2. Setter 和 Getter方法注:FastJson在进行操作时,是根据getter和setter的方法进行的,并不是依据Field进行。
Show me the code:
一、作用Field
@JSONField作用在Field时,其name不仅定义了输入key的名称,同时也定义了输出的名称。当@JSONField作用在Fileld上时,定义了输入和输出,如果我们传输过来的json格式不符合这个格式时,则不能够正确转换。
二、作用在setter和getter方法上
顾名思义,当作用在setter方法上时,就相当于根据 name 到 json中寻找对应的值,并调用该setter对象赋值。
当作用在getter上时,在bean转换为json时,其key值为name定义的值。
下面是对getwhereString的解析
Set<Entry<String, List<String>>> combineSet = combine == null ? null : combine.entrySet();
这里使用set方法定义了combineSet
知识学习
Set是集合的意思,是同种对象的集合,<String>说明这种对象都是String类型的对象。
可以这样:
Set<String> set = new HashSet<String>();
String s1 = "hello";String s2 = "world";
set.add(s1);
set.add(s2);
这样就添加了两个元素。
for (Entry<String, List<String>> ce : combineSet) {
keyList = ce == null ? null : ce.getValue();
if (keyList == null || keyList.isEmpty()) {
continue;
}
if ("|".equals(ce.getKey())) {
logic = Logic.TYPE_OR;
}
else if ("!".equals(ce.getKey())) {
logic = Logic.TYPE_NOT;
}
else {
logic = Logic.TYPE_AND;
}
isItemFirst = true;
cs = "";
for (String key : keyList) {
c = getWhereItem(key, where.get(key), method, verifyName);
if (StringUtil.isEmpty(c, true)) {//避免SQL条件连接错误
continue;
}
cs += (isItemFirst ? "" : (Logic.isAnd(logic) ? AND : OR)) + "(" + c + ")";
isItemFirst = false;
}
if (StringUtil.isEmpty(cs, true)) {//避免SQL条件连接错误
continue;
}
whereString += (isCombineFirst ? "" : AND) + (Logic.isNot(logic) ? NOT : "") + " ( " + cs + " ) ";
isCombineFirst = false;
}
这里是对SQL语言中WHERE语句的SQL连接,条件的判断,后面还有对join的错误类型判断,大概分以下几种
throw new NotExistException("no result for ! OUTER JOIN( ! (A | B) ) when A or B is empty!")
throw new NotExistException("no result for ) FOREIGN JOIN( B & ! A ) when A is empty!");
throw new NotExistException("no result for ! OUTER JOIN( ! (A | B) ) when A or B is empty!");
throw new NotExistException("no result for ( ANTI JOIN( A & ! B ) when B is empty!");
throw new NotExistException("no result for ^ SIDE JOIN( ! (A & B) ) when both A and B are empty!");
throw new UnsupportedOperationException("写操作请求必须带条件!!!");
protected String getWhereItem(String key, Object value, RequestMethod method, boolean verifyName) throws Exception {
Log.d(TAG, "getWhereItem key = " + key);
//避免筛选到全部 value = key == null ? null : where.get(key);
if (key == null || value == null || key.endsWith("()") || key.startsWith("@")) { //关键字||方法, +或-直接报错
Log.d(TAG, "getWhereItem key == null || value == null"
+ " || key.startsWith(@) || key.endsWith(()) >> continue;");
return null;
}
if (key.endsWith("@")) {//引用
// key = key.substring(0, key.lastIndexOf("@"));
throw new IllegalArgumentException(TAG + ".getWhereItem: 字符 " + key + " 不合法!");
}
// 原始 SQL 片段
String rawSQL = getRawSQL(key, value);
int keyType;
if (key.endsWith("$")) {
keyType = 1;
}
else if (key.endsWith("~")) {
keyType = key.charAt(key.length() - 2) == '*' ? -2 : 2; //FIXME StringIndexOutOfBoundsException
}
else if (key.endsWith("%")) {
keyType = 3;
}
else if (key.endsWith("{}")) {
keyType = 4;
}
else if (key.endsWith("}{")) {
keyType = 5;
}
else if (key.endsWith("<>")) {
keyType = 6;
}
else if (key.endsWith(">=")) {
keyType = 7;
}
else if (key.endsWith("<=")) {
keyType = 8;
}
else if (key.endsWith(">")) {
keyType = 9;
}
else if (key.endsWith("<")) {
keyType = 10;
} else { // else绝对不能省,避免再次踩坑! keyType = 0; 写在for循环外面都没注意!
keyType = 0;
}
key = getRealKey(method, key, false, true, verifyName);
switch (keyType) {
case 1:
return getSearchString(key, value, rawSQL);
case -2:
case 2:
return getRegExpString(key, value, keyType < 0, rawSQL);
case 3:
return getBetweenString(key, value, rawSQL);
case 4:
return getRangeString(key, value, rawSQL);
case 5:
return getExistsString(key, value, rawSQL);
case 6:
return getContainString(key, value, rawSQL);
case 7:
return getCompareString(key, value, ">=", rawSQL);
case 8:
return getCompareString(key, value, "<=", rawSQL);
case 9:
return getCompareString(key, value, ">", rawSQL);
case 10:
return getCompareString(key, value, "<", rawSQL);
default: // TODO MySQL JSON类型的字段对比 key='[]' 会无结果! key LIKE '[1, 2, 3]' //TODO MySQL , 后面有空格!
return getEqualString(key, value, rawSQL);
}
}
这里对不同的符号进行了不同的处理
用到了后面定义的方法getRegExpString, getBetweenString,getRangeString,getExistsString, getContainString,getEqualString下一篇博客会来分析一下这些方法
下面是getRegExpString
@JSONField(serialize = false)
public String getRegExpString(String key, Object value, boolean ignoreCase, 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, "getRegExpString key = " + key);
JSONArray arr = newJSONArray(value);
if (arr.isEmpty()) {
return "";
}
return getRegExpString(key, arr.toArray(), logic.getType(), ignoreCase);
}
/**search key match RegExp values
* @param key
* @param values
* @param type
* @param ignoreCase
* @return LOGIC [ key REGEXP 'values[i]' ]
* @throws IllegalArgumentException
*/
@JSONField(serialize = false)
public String getRegExpString(String key, Object[] values, int type, boolean ignoreCase) throws IllegalArgumentException {
if (values == null || values.length <= 0) {
return "";
}
String condition = "";
for (int i = 0; i < values.length; i++) {
if (values[i] instanceof String == false) {
throw new IllegalArgumentException(key + "$:value 中value的类型只能为String或String[]!");
}
condition += (i <= 0 ? "" : (Logic.isAnd(type) ? AND : OR)) + getRegExpString(key, (String) values[i], ignoreCase);
}
return getCondition(Logic.isNot(type), condition);
}
/**WHERE key REGEXP 'value'
* @param key
* @param value
* @param ignoreCase
* @return key REGEXP 'value'
*/
@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);
}
这里也用到了Log中的方法
public static boolean DEBUG = true;
public static void d(String TAG, String msg) {
if (DEBUG) {
logInfo(TAG,msg,"DEBUG");
}
}
这里又用到了loginfo方法如下
public static void logInfo(String TAG, String msg, String level){
if(level.equals("DEBUG") || level .equals("ERROR") ||level.equals("WARN")){
System.err.println(dateFormat.format(System.currentTimeMillis()) + ": " + TAG + "." + level + ": " + msg);
}
else if(level.equals("VERBOSE") || level .equals("INFO") ){
System.out.println(dateFormat.format(System.currentTimeMillis()) + ": " + TAG + "." + level + ": " + msg);
}
}
这是对调用方法的日志信息表记录,出错时和未出错时的记录
知识学习
System.err和System.out的区别?
①java API,文档中给出的解释是:out为“标准输出流”,err为“标准错误输出流”;②在eclipse里运行时差别就是,二者显示的颜色有所区别,err输出显示为红色 ;
③err.println输出的字符串位置会随机出现。但,err.println输出的字符串之间的相对位置不会改变,System.out在JVM和操作系统都具有缓存功能,就是你输出的东西不一定实时输出,有时候会积攒到一定数量才会输出,System.err会实时输出,单独使用的话可能感觉不到,如果两种方式混合使用就会发现了 。
记录位置1957