edi.rule.model.JSRuleGet Maven / Gradle / Ivy
package edi.rule.model;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.fasterxml.jackson.annotation.JsonIgnore;
import edi.rule.annotation.JSRuleCheck;
import edi.rule.annotation.JSRuleInject;
import edi.rule.config.JSRuleMessage;
import edi.rule.core.JSRuleArgsVessel;
import edi.rule.core.JSRuleJdbc;
import edi.rule.core.JSRuleMethod;
import edi.rule.util.*;
import edi.rule.work.constant.ZSSign;
import edi.rule.work.enums.JSRuleCrudEnum;
import edi.rule.work.custom.JSRuleException;
import edi.rule.work.cache.JSRuleMappingInfo;
import edi.rule.work.constant.JSRuleJsonValue;
import edi.rule.work.interfaces.IJSRuleCrudModel;
import edi.rule.work.interfaces.IJSRuleSql;
import lombok.Data;
/**
* @author 摩拉克斯
* @date 2022年1月4日 上午9:18:47
*/
@Data
public class JSRuleGet> implements IJSRuleCrudModel,IJSRuleSql{
/**
* 映射类之间的关联关系对象
* */
@JSRuleCheck(required=true)
public JSRuleRelations relation;
/**
*
条件对象
* */
@JSRuleCheck
public JSRuleConditions condition;
/**
*
union功能,支持多个连续union
* */
@JSRuleCheck
public List unions;
/**
* 是否使用框架内置的解析器解析json形成所要执行的sql语句,默认为true
*
如果你想自定义sql解析器则应设置为false并实现{@link JSRuleGet#beforeSql(String,JSRuleAction)}
* */
public Boolean convertSql;
/**
*
是否执行最终形成的sql语句,默认为true,为false时将返回sql语句,子查询或union时使用的仅是其解析后的sql,并不需要真正的执行,因此可将其设置为false以避免多余的计算
* */
public Boolean execute;
/**
*
分页对象
* */
public JSPage page;
/**
*
所要查询的字段,为空或者为null时则查询全部字段,是po类中所配置的全部字段
* */
public List fields;
/**
* 排序属性,保证先写先排,key为排序字段名,value为排序方式,仅可以为asc或desc
* */
@JSRuleCheck(values= {JSRuleJsonValue.ORDER_ASC,JSRuleJsonValue.ORDER_DESC})
public LinkedHashMap order;
/**
* 分组对象
* */
@JSRuleCheck
public JSRuleGroups group;
/**
*
是否以分组的方式回显数据,默认为false,用于多表联查时区分字段属于哪个表的,还可通过别名表达式来动态指定分组,未找到分组的字段将不会加入到分组类中
* */
public Boolean groupShow;
/**
*
一对多,多对一,递归层级展示
* */
@JSRuleCheck
public JSRuleProfile profile;
@JSRuleInject
@JsonIgnore
private JSRuleArgsVessel vessel;
@JSRuleInject
@JsonIgnore
private JSRuleJdbc jdbc;
public JSRuleGet() {
convertSql = true;
execute = true;
groupShow = false;
page = new JSPage();
}
@Override
public final Object startCrudModel(A action) {
StringBuilder builder = new StringBuilder();
if (getConvertSql()) {
String relationsText = JSRuleMethod.addRelations(getRelation(),action.cache, vessel.getActionArgs());
String conditionsText = JSRuleMethod.addConditions(getCondition(),action.cache, vessel.getActionArgs());
final boolean isConditionsTextEmpty = ZSString.isBlank(conditionsText);
final boolean isRelationsTextEmpty = ZSString.isBlank(relationsText);
if (profileShow()) {
for (Entry entry:action.cache.mappingsInfo.entrySet()) {
if (getFields().contains(ZSRule.getPrefixClassFieldText(entry.getValue().className, entry.getValue().getPk()))) continue;
throw new JSRuleException(action.cache.name, JSRuleMessage.read("the.property.of.fields.should.include.primary.key"));
}
}
builder.append("select ").append(JSRuleMethod.addFields(this, action.cache)).append(" from ");
if (getRelation().haveJoins()) {
builder.append(isRelationsTextEmpty?JSRuleMethod.getSubject(action.cache.getMainInfo(getRelation()),action.cache,true):relationsText);
if (!isConditionsTextEmpty) {
builder.append(where).append(conditionsText);
}
}else {
builder.append(action.cache.getActionSubject());
if (ZSString.isNotBlank(relationsText) || !isConditionsTextEmpty) {
builder.append(where).append(relationsText);
if (!isConditionsTextEmpty) {
if (!isRelationsTextEmpty) {
StringBuilder conditionsBuffer = new StringBuilder(conditionsText);
if (JSRuleJsonValue.TYPE_OR.equals(getCondition().type)) {
conditionsBuffer.insert(0, ZSSign.LEFT_BRACKET).append(ZSSign.RIGHT_BRACKET);
}
conditionsBuffer.insert(0, " and ");
builder.append(conditionsBuffer);
}else {
builder.append(conditionsText);
}
}
}
}
builder.append(JSRuleMethod.addGroup(this,action.cache, vessel.getActionArgs()));
builder.append(JSRuleMethod.addOrder(this,action.cache));
if (ZSVessel.isNotEmpty(getUnions())) {
builder.insert(0,ZSSign.LEFT_BRACKET).append(ZSSign.RIGHT_BRACKET);
for (JSRuleUnion union:getUnions()) {
builder.append(ZSSign.BLANK).append(union.getTypeText()).append(union.getPointer().getPointText(action.cache, vessel, false));
}
}
}
String sql = builder.toString();
sql = beforeSql(sql,action);
vessel.getActionArgs().get(action.cache.name).setSql(sql);
if (!getExecute()) {
return sql;
}
JSPage result;
boolean isProfileShow = profileShow();
if (isProfileShow) {
result = new JSPage(getPage().getPageNum(),getPage().getPageSize());
result.setData(jdbc.get(sql));
setGroupShow(true);
}else {
result = jdbc.page(sql,getPage().getPageNum(),getPage().getPageSize());
}
if (getGroupShow()) {
result.setData(JSRuleMethod.toGroupShow(result.getData(),action.cache));
if (isProfileShow) {
result = ZSData.getJSPage(JSRuleMethod.toProfileShow(getProfile(), result.getData(), action.cache),result.getPageNum(),result.getPageSize());
}
}else {
JSRuleMethod.toDefaultShow(result.getData(),action.cache);
}
for (Map data:result.getData()) {
dataProcess(data,action);
}
return result;
}
/**
* 检查映射类信息以及对应的角色信息是否具有get操作权限
* @apiNote 抽象方法不要在for循环里调用,因为子类的逻辑有可能会重复执行,应该设置一个变量指向其抽象方法的结果,如roles()
* */
@Override
public final void checkCrudPermit(A action) {
for (String className:relation.classNames){
ZSRule.checkCrudPermit(action.name,className,JSRuleCrudEnum.R, vessel.getGlobalArgs().getRoles());
}
}
/**
*
判断是否需要ProfileShow进行递归层级一对多,多对一的展示
* */
public boolean profileShow() {
return getProfile()!=null;
}
/**
*
扩展处理查询数据前的sql语句
* @param sql 拼装后的sql语句,action 所要执行的动作对象
* */
protected String beforeSql(String sql,A action) {
return sql;
}
/**
*
扩展处理返回响应前的数据结果集
* @param data 代表1条数据
* */
protected void dataProcess(Map data,A action) {}
}