
cn.org.atool.fluent.mybatis.segment.model.WrapperData Maven / Gradle / Ivy
package cn.org.atool.fluent.mybatis.segment.model;
import cn.org.atool.fluent.mybatis.If;
import cn.org.atool.fluent.mybatis.base.model.Column;
import cn.org.atool.fluent.mybatis.base.model.ISqlOp;
import cn.org.atool.fluent.mybatis.exception.FluentMybatisException;
import cn.org.atool.fluent.mybatis.segment.WhereSegmentList;
import cn.org.atool.fluent.mybatis.utility.CustomizedSql;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import java.util.*;
import java.util.function.Supplier;
import static cn.org.atool.fluent.mybatis.If.isBlank;
import static cn.org.atool.fluent.mybatis.If.notBlank;
import static cn.org.atool.fluent.mybatis.mapper.StrConstant.*;
import static cn.org.atool.fluent.mybatis.utility.MybatisUtil.*;
import static java.util.stream.Collectors.joining;
/**
* WrapperInfo: 查询器或更新器xml需要用到信息
*
* @author darui.wu 2020/6/23 5:15 下午
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Getter
public class WrapperData implements IWrapperData {
/**
* select 前面是否加 DISTINCT 关键字
*/
@Setter
protected boolean isDistinct = false;
/**
* 查询字段
*/
protected List sqlSelect = new ArrayList<>(8);
/**
* 表名
*/
@Getter(AccessLevel.NONE)
protected Supplier table;
@Setter
private String alias;
/**
* 自定义参数列表
*/
protected final Parameters parameters;
/**
* where, group, having ,order by对象列表
*/
protected final MergeSegments mergeSegments = new MergeSegments();
/**
* 分页参数
*/
@Setter
protected PagedOffset paged;
/**
* SQL 更新字段内容,例如:name='1', age=2
*/
private final Map updates = new LinkedHashMap<>(16);
/**
* sql 中 hint 维护
*/
private final Map hints = new HashMap<>(4);
/**
* 实体类型
*/
private final Class entityClass;
/**
* 对应的嵌套查询类
*/
private final Class queryClass;
/**
* 字段别名列表
*/
private final Set fieldAlias = new HashSet<>();
/**
* 按条件更新时, 跳过检查乐观锁条件字段
* 默认必须有乐观锁
*/
@Setter
private boolean ignoreLockVersion = false;
public WrapperData() {
this.parameters = new Parameters();
this.queryClass = null;
this.entityClass = null;
}
public WrapperData(Supplier table, String alias, Parameters parameters, Class entityClass, Class queryClass) {
notNull(entityClass, "entityClass must not null,please set entity before use this method!");
this.table = table;
this.alias = alias;
this.parameters = parameters;
this.entityClass = entityClass;
this.queryClass = queryClass;
}
public String getTable() {
return isBlank(alias) ? this.table.get() : this.table.get() + " " + this.alias;
}
@Override
public String getSqlSelect() {
if (this.sqlSelect.isEmpty()) {
return null;
} else {
String sql = String.join(COMMA_SPACE, sqlSelect);
return isBlank(sql) ? null : sql.trim();
}
}
public List sqlSelect() {
return this.sqlSelect;
}
/**
* 用户完整自定义的sql语句
*/
private String customizedSql = null;
/**
* 自定义的完整sql语句设置
*
* @param sql sql
* @param parameter 参数
*/
public void customizedSql(String sql, Object parameter) {
if (parameter == null) {
this.customizedSql = sql;
} else {
this.customizedSql = CustomizedSql.rewriteSql(sql, this.parameters, parameter);
}
}
@Override
public String getQuerySql() {
if (If.notBlank(customizedSql)) {
return customizedSql;
}
String select = this.getSqlSelect();
String where = this.getWhereSql();
String sql = "SELECT" + SPACE +
(isBlank(select) ? ASTERISK : select.trim()) + SPACE +
"FROM" + SPACE +
this.getTable() + SPACE +
(isBlank(where) ? EMPTY : "WHERE " + where.trim()) + SPACE +
this.getGroupBy().trim() + SPACE +
this.getOrderBy().trim() + SPACE +
this.getLastSql().trim();
return sql.trim();
}
@Override
public String getUpdateStr() {
String sql = this.updates.entrySet().stream().map(i -> i.getKey() + " = " + i.getValue()).collect(joining(COMMA_SPACE));
return isBlank(sql) ? null : sql.trim();
}
@Override
public String getMergeSql() {
String sql = mergeSegments.sql();
return isBlank(sql) ? null : sql.trim();
}
@Override
public String getWhereSql() {
return this.mergeSegments.whereSql();
}
@Override
public String getGroupBy() {
return this.mergeSegments.groupBy();
}
@Override
public String getOrderBy() {
return this.mergeSegments.orderBy();
}
@Override
public String getLastSql() {
return this.mergeSegments.last();
}
/*
* ============================================================
* 以下是数据操作部分
* ============================================================
*/
/**
* 附加sql,只允许执行一次
*
* @param lastSql 附加sql
*/
public void last(String lastSql) {
this.mergeSegments.setLastSql(lastSql);
}
/**
* 增加条件设置
*
* @param keyWord or and
* @param column 设置条件的字段
* @param operator 条件操作
* @param paras 条件参数(填充 operator 中占位符?)
*/
public void apply(KeyWordSegment keyWord, Column column, ISqlOp operator, Object... paras) {
this.apply(keyWord, column, operator, null, paras);
}
/**
* 增加查询字段
*
* @param column 字段
*/
public void addSelectColumn(String column) {
if (notBlank(column)) {
this.sqlSelect.add(column);
this.fieldAlias.addAll(parseAlias(column));
}
}
/**
* 解析别名列表
*
* @param column 字段
* @return ignore
*/
static List parseAlias(String column) {
int pos = -1;
List list = new ArrayList<>();
StringBuilder buff = new StringBuilder();
for (char c : (column + SPACE).toCharArray()) {
if (pos <= 0 && isSpace(c)) {
pos = 0;
} else if (pos == 0 && (c == 'a' || c == 'A')) {
pos = 1;
} else if (pos == 1 && (c == 's' || c == 'S')) {
pos = 2;
} else if ((pos == 2 || pos == 3) && isSpace(c)) {
pos = 3;
} else if (pos >= 3 && (isLetter(c) || isDigit(c))) {
pos = 4;
buff.append(c);
} else if (pos == 4 && (isSpace(c) || c == ',')) {
list.add(buff.toString());
buff = new StringBuilder();
pos = -1;
} else {
pos = -1;
}
}
return list;
}
/**
* 增加条件设置
*
* @param keyWord or and
* @param column 设置条件的字段
* @param operator 条件操作
* @param format 格式化sql语句
* @param args 条件参数(填充 operator 中占位符?)
*/
public void apply(KeyWordSegment keyWord, Column column, ISqlOp operator, String format, Object... args) {
if (keyWord == null) {
throw new FluentMybatisException("the first segment should be: 'AND', 'OR', 'GROUP BY', 'HAVING' or 'ORDER BY'");
}
String segment = operator.operator(column, this.getParameters(), format, args);
this.getMergeSegments().add(keyWord, column.columnSegment(), () -> segment);
}
public void apply(KeyWordSegment keyWord, ISqlSegment... segments) {
if (keyWord == null) {
throw new FluentMybatisException("the first segment should be: 'AND', 'OR', 'GROUP BY', 'HAVING' or 'ORDER BY'");
}
this.getMergeSegments().add(keyWord, segments);
}
/**
* 根据函数和变量构建占位符和设置占位符对应的变量值
*
* @param column 映射字段, 如果 = null, 表示非原始字段赋值
* @param functionSql 函数
* @param values 变量列表
* @return 参数化后的sql
*/
public String paramSql(Column column, String functionSql, Object[] values) {
return this.parameters.paramSql(column, functionSql, values);
}
/**
* 更新column字段值
*
* @param column 被更新字段
* @param value 更新值
*/
public void updateSet(Column column, Object value) {
this.updateSql(column, QUESTION_MARK, value);
}
/**
* 设置更新(自定义SQL)
*
* @param column 更新的字段
* @param functionSql set function sql
* @param values 对应的参数
*/
public void updateSql(Column column, String functionSql, Object... values) {
if (notBlank(functionSql)) {
updates.put(column.wrapColumn(), this.paramSql(column, functionSql, values));
}
}
/**
* 获取where条件字段
*
* @return ignore
*/
public List findWhereColumns() {
WhereSegmentList list = this.getMergeSegments().getWhere();
if (list == null || list.getSegments() == null) {
return Collections.EMPTY_LIST;
}
List columns = new ArrayList<>();
for (ISqlSegment segment : list.getSegments()) {
if (segment instanceof ColumnSegment) {
columns.add(segment.getSqlSegment());
}
}
return columns;
}
public void hint(HintType type, String hint) {
if (notBlank(hint)) {
this.hints.put(type, hint);
}
}
public String hint(HintType type) {
String hint = this.hints.get(type);
return isBlank(hint) ? SPACE : SPACE + hint + SPACE;
}
public void sharedParameter(WrapperData wrapperData) {
this.getParameters().sharedParameter(wrapperData.getParameters());
}
public void sharedParameter(Parameters parameters) {
this.getParameters().sharedParameter(parameters);
}
public ISqlSegment[] whereSegments() {
return this.mergeSegments.getWhere().getSegments().toArray(new ISqlSegment[0]);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy