/**
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.toolkit.StringUtils;
/**
* <p>
* 重定义 AbstractSQL ,实现标准TSQL的 查询条件自定义
* </p>
*
* @author yanghu
* @Date 2016-08-22
*/
@SuppressWarnings("serial")
public abstract class MybatisAbstractSQL<T> implements Serializable {
private static final String AND = " AND ";
private static final String OR = " OR ";
private static final String AND_NEW = ") \nAND (";
private static final String OR_NEW = ") \nOR (";
/**
* SQL条件
*/
private final SQLCondition sql = new SQLCondition();
/**
* 子类泛型实现
*
* @return 泛型实例
*/
public abstract T getSelf();
public T WHERE(String conditions) {
sql().where.add(conditions);
sql().lastList = sql().where;
return getSelf();
}
public T OR() {
sql().lastList.add(OR);
return getSelf();
}
public T OR_NEW() {
sql().lastList.add(OR_NEW);
return getSelf();
}
public T AND() {
sql().lastList.add(AND);
return getSelf();
}
public T AND_NEW() {
sql().lastList.add(AND_NEW);
return getSelf();
}
public T GROUP_BY(String columns) {
sql().groupBy.add(columns);
return getSelf();
}
public T HAVING(String conditions) {
sql().having.add(conditions);
sql().lastList = sql().having;
return getSelf();
}
public T ORDER_BY(String columns) {
sql().orderBy.add(columns);
return getSelf();
}
public T LAST(String last) {
sql().last = last;
return getSelf();
}
private SQLCondition sql() {
return sql;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sql().sql(sb);
return sb.toString();
}
/**
* SQL连接器
*/
private static class SafeAppendable implements Serializable {
private final Appendable appendable;
private boolean empty = true;
public SafeAppendable(Appendable appendable) {
super();
this.appendable = appendable;
}
public SafeAppendable append(CharSequence charSequence) {
try {
if (empty && charSequence.length() > 0) {
empty = false;
}
appendable.append(charSequence);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public boolean isEmpty() {
return empty;
}
}
/**
* SQL条件类
*/
private static class SQLCondition implements Serializable {
final List<String> where = new ArrayList<>();
final List<String> having = new ArrayList<>();
final List<String> groupBy = new ArrayList<>();
final List<String> orderBy = new ArrayList<>();
final List<String> andOr = new ArrayList<>();
String last = null;
List<String> lastList = new ArrayList<>();
public SQLCondition() {
andOr.add(AND);
andOr.add(OR);
andOr.add(AND_NEW);
andOr.add(OR_NEW);
}
/**
* 构建SQL的条件
*
* @param builder 连接器
* @param keyword TSQL中的关键字
* @param parts SQL条件语句集合
* @param open 起始符号
* @param close 结束符号
* @param conjunction 连接条件
*/
private void sqlClause(SafeAppendable builder, String keyword, List<String> parts, String open, String close,
String conjunction) {
parts = clearNull(parts);
if (!parts.isEmpty()) {
if (!builder.isEmpty()) {
builder.append("\n");
}
builder.append(keyword);
builder.append(" ");
builder.append(open);
String last = "__";
for (int i = 0, n = parts.size(); i < n; i++) {
String part = parts.get(i);
if (i > 0) {
if (andOr.contains(part) || andOr.contains(last)) {
builder.append(part);
last = part;
continue;
} else {
builder.append(conjunction);
}
}
builder.append(part);
}
builder.append(close);
}
}
/**
* 清除LIST中的NULL和空字符串
*
* @param parts 原LIST列表
* @return
*/
private List<String> clearNull(List<String> parts) {
List<String> temps = new ArrayList<>();
for (String part : parts) {
if (StringUtils.isEmpty(part)) {
continue;
}
temps.add(part);
}
return temps;
}
/**
* 按标准顺序连接并构建SQL
*
* @param builder 连接器
* @return
*/
private String buildSQL(SafeAppendable builder) {
sqlClause(builder, "WHERE", where, "(", ")", AND);
sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
sqlClause(builder, "HAVING", having, "(", ")", AND);
sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
if (StringUtils.isNotEmpty(last)) {
builder.append(" ");
builder.append(last);
}
return builder.toString();
}
public String sql(Appendable appendable) {
return buildSQL(new SafeAppendable(appendable));
}
}
}