EKP其它/EKPSQL工具

1、说明

有时候想在前端快速查询一些数据,ekp自带的第三方集成jdbc也可以用,但怎么说呢,总之用得很不爽!所以就有了以下的扩展。

功能大概是这样的:前端写好纯sql,前端根据关键字传入参数进行调用,获取到查询结果,并支持SQL开窗

2、效果图

 低代码:

 

 

 

 

 开窗效果:

开窗应用,具体可看本人文章: 自定义表单控件 - 扩展出一个选择框_Liquid-Li的博客-CSDN博客

 3、具体实现 - 后端service

package com.landray.kmss.xpcommon.service.spring;

import cn.hutool.core.lang.func.VoidFunc1;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.db.ds.simple.SimpleDataSource;
import cn.hutool.db.transaction.TransactionLevel;
import com.alibaba.fastjson.JSONObject;
import com.landray.kmss.common.service.BaseServiceImp;
import com.landray.kmss.component.dbop.model.CompDbcp;
import com.landray.kmss.component.dbop.service.ICompDbcpService;
import com.landray.kmss.util.SpringBeanUtil;
import com.landray.kmss.util.StringUtil;
import com.landray.kmss.xp.util.XpStringUtil;

import javax.sql.DataSource;
import java.util.*;

public abstract class XpSqlBaseServiceImp extends BaseServiceImp{
    private ICompDbcpService compDbcpService;
    private Db db;

    public abstract String getDbSourceId();

    public ICompDbcpService getCompDbcpService() {
        if (compDbcpService == null) {
            compDbcpService = (ICompDbcpService) SpringBeanUtil.getBean("compDbcpService");
        }
        return compDbcpService;
    }

    public Db getDb() throws Exception {
        if (db == null || db.getConnection().isClosed()) {
            ICompDbcpService compDbcpService = getCompDbcpService();
            CompDbcp compDbcp = (CompDbcp) compDbcpService.findByPrimaryKey(this.getDbSourceId());// 数据源对象
            DataSource ds = new SimpleDataSource(compDbcp.getFdUrl(), compDbcp.getFdUsername(), compDbcp.getFdPassword());
            db = Db.use(ds);
        }
        return db;
    }

    /**
     * 执行sql获取查询结果(一维List,元素为Entity对象)
     * @author liquid
     * @date 2022年10月11日
     * @param sql SQL
     * @param params 参数集合
     *               如需分页操作,请在子类重新该方法,根据params._fixed{firstResult,maxResults}进行特殊处理
     * @return 查询结果数据
     */
    public List<Entity> executeQueryToEntity(String sql, JSONObject params) {
        List<Entity> entityList;
        try {
            entityList = getDb().query(sql, params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return entityList;
    }

    /**
     * 执行sql获取查询结果(二维List,元素为具体数据对象)
     * @author liquid
     * @date 2022年10月11日
     * @param sql SQL
     * @param params 参数集合
     *               可传入固定参数 _fixed{
     *                  firstResult: 0,
     *                  maxResults: 10
     *               } 从第0条记录开始取10条数据
     * @return 查询结果数据
     */
    public List executeQuery(String sql, JSONObject params) {
        List<List<Object>> rtnList = new ArrayList<>();
        List<Entity> queryList = this.executeQueryToEntity(sql, params);
        if (queryList.size() == 0) {
            return rtnList;
        }
        // Entity 转 List 后返回
        Set<String> fieldNames = queryList.get(0).getFieldNames();
        for (Entity entity : queryList) {
            List<Object> row = new ArrayList<>();
            for (String fieldName : fieldNames) {
                row.add(entity.get(fieldName));
            }
            rtnList.add(row);
        }
        return rtnList;
    }

    /**
     * 执行sql获取查询结果(一维List,元素为Map对象)
     * @author liquid
     * @date 2022年10月11日
     * @param sql SQL
     * @param params 参数集合
     *               可传入固定参数 _fixed{
     *                  firstResult: 0,
     *                  maxResults: 10
     *               } 从第0条记录开始取10条数据
     * @return 查询结果数据
     */
    public List executeQueryToMap(String sql, JSONObject params) {
        List<Map<String, Object>> rtnList = new ArrayList<>();
        List<Entity> queryList = this.executeQueryToEntity(sql, params);
        if (queryList.size() == 0) {
            return rtnList;
        }
        // Entity 转 Map 后返回
        Set<String> fieldNames = queryList.get(0).getFieldNames();
        for (Entity entity : queryList) {
            Map<String, Object> row = new HashMap<>();
            for (String fieldName : fieldNames) {
                row.put(fieldName, entity.get(fieldName));
            }
            rtnList.add(row);
        }
        return rtnList;
    }

    /**
     * 执行sql写入操作
     * ekp数据库,执行写操作sql(多条sql语句,加入事务管理)
     * @author liquid
     * @date 2023年2月2日
     * @param sqlList sql语句列表
     * @param paramsList sql语句参数列表
     *                   (注意该参数和sqlList的元素个数需一致,若对应sql无需传参则new一个空的JOSNObject进去)
     * @return 是否执行成功(1成功,0失败)
     */
    public String executeUpdate(List<String> sqlList, List<JSONObject> paramsList) {
        String status;
        try {
            Db db = getDb();
            db.tx(TransactionLevel.READ_COMMITTED, (VoidFunc1<Db>) thisDb -> {
                for (int i = 0; i < sqlList.size(); i++) {
                    thisDb.execute(sqlList.get(i), paramsList.get(i));
                }
            });
            status = XpStringUtil.CODE_SUCCESS;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return status;
    }

    /**
     * 执行sql写入操作
     * @author liquid
     * @date 2023年3月2日
     * @param sql sql语句
     * @param param json参数
     * @return 是否执行成功(1成功,0失败)
     */
    public String executeUpdate(String sql, JSONObject param) {
        if (StringUtil.isNull(sql)) {
            return XpStringUtil.CODE_ERROR;
        }
        List<String> sqlList = new ArrayList<>();
        List<JSONObject> paramsList = new ArrayList<>();
        sqlList.add(sql);
        paramsList.add(param);
        return executeUpdate(sqlList, paramsList);
    }

    /**
     * 获取sql查询结果个数
     * @author liquid
     * @date 2022年11月2日
     * @param sql SQL
     * @param params 参数集合
     * @return 查询结果个数
     */
    public long getQueryMaxCount(String sql, JSONObject params) {
        Db db;
        long maxCount;
        try {
            db = getDb();
            maxCount = db.count(sql, params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return maxCount;
    }
}
package com.landray.kmss.xpcommon.service.spring;

import cn.hutool.db.Entity;
import com.alibaba.fastjson.JSONObject;
import com.landray.kmss.xp.modeling.app.it.util.XpSqlUtil;
import com.landray.kmss.xp.util.enums.XpDbType;

import java.util.List;

public abstract class XpSqlBaseOracleServiceImp  extends XpSqlBaseServiceImp {
    /**
     * 执行sql获取查询结果(一维List,元素为Entity对象)
     * @author liquid
     * @date 2022年10月11日
     * @param sql SQL(分页查询:SELECT ROWNUM rowno, V_GROUP_USER_02.* FROM V_GROUP_USER_02 WHERE ORGNAME = :ORGNAME)
     * @param params 参数集合
     *               可传入固定参数 _fixed{
     *                  firstResult: 0,
     *                  maxResults: 10
     *               } 从第0条记录开始取10条数据
     * @return 查询结果数据
     */
    @Override
    public List<Entity> executeQueryToEntity(String sql, JSONObject params) {
        List<Entity> entityList;
        // 固定参数
        if (params.containsKey("_fixed")) {
            JSONObject fixed = params.getJSONObject("_fixed");
            Integer firstResult = fixed.getInteger("firstResult");
            Integer maxResults = fixed.getInteger("maxResults");
            // 构造分页sql
            if (firstResult != null && maxResults != null) {
                sql = XpSqlUtil.makePagingSql(XpDbType.DB_TYPE_ORACLE, sql, firstResult, maxResults);
            }
        }
        try {
            entityList = getDb().query(sql, params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        entityList.forEach(entity -> {
            entity.remove("rowno");
            entity.getFieldNames().remove("rowno");
        });

        return entityList;
    }
}

package com.landray.kmss.xp.modeling.app.it.service.spring;

import com.landray.kmss.xp.modeling.app.it.constant.XpCompDbcpConstant;
import com.landray.kmss.xpcommon.service.spring.XpSqlBaseOracleServiceImp;

public class XpEkpSqlBpmServiceImp extends XpSqlBaseOracleServiceImp {
    @Override
    public String getDbSourceId() {
        return XpCompDbcpConstant.DB_SOURCE_ID_BPM;
    }
}

package com.landray.kmss.xp.modeling.app.it.service.spring;

import com.landray.kmss.xp.modeling.app.it.constant.XpCompDbcpConstant;
import com.landray.kmss.xpcommon.service.spring.XpSqlBaseOracleServiceImp;

/**
 * @author liquid
 */
public class XpEkpSqlErpServiceImp extends XpSqlBaseOracleServiceImp {
    @Override
    public String getDbSourceId() {
        return XpCompDbcpConstant.DB_SOURCE_ID_ERP;
    }
}
package com.landray.kmss.xp.modeling.app.it.service.spring;

import com.alibaba.fastjson.JSONObject;
import com.landray.kmss.util.IDGenerator;
import com.landray.kmss.util.StringUtil;
import com.landray.kmss.xp.util.XpStringUtil;
import com.landray.kmss.xpcommon.service.spring.XpSqlBaseServiceImp;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.NativeQuery;
import org.hibernate.transform.Transformers;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author liquid
 * @date 2022年10月10日
 */
public class XpEkpSqlEkpServiceImp extends XpSqlBaseServiceImp {
    @Override
    public String getDbSourceId() {
        return null;// ekp数据库不使用数据源中的链接信息
    }

    @Override
    public List executeQuery(String sql, JSONObject params) {
        NativeQuery query = super.getBaseDao().getHibernateSession().createNativeQuery(sql);
        params.keySet().parallelStream().forEach(key -> {
            // 如果是固定参数
            if ("_fixed".equals(key)) {
                JSONObject fixed = params.getJSONObject(key);
                Integer firstResult = fixed.getInteger("firstResult");
                Integer maxResults = fixed.getInteger("maxResults");
                if (firstResult != null) {
                    query.setFirstResult(fixed.getInteger("firstResult"));
                }
                if (maxResults != null) {
                    query.setMaxResults(fixed.getInteger("maxResults"));
                }
            }
            else {
                query.setParameter(key, params.get(key));
            }
        });
        return query.list();
    }

    @Override
    public List executeQueryToMap(String sql, JSONObject params) {
        NativeQuery query = super.getBaseDao().getHibernateSession().createNativeQuery(sql);
        params.keySet().parallelStream().forEach(key -> {
            // 如果是固定参数
            if ("_fixed".equals(key)) {
                JSONObject fixed = params.getJSONObject(key);
                query.setFirstResult(fixed.getInteger("firstResult"));
                query.setMaxResults(fixed.getInteger("maxResults"));
            }
            else {
                query.setParameter(key, params.get(key));
            }
        });
        return query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
    }

    @Override
    public String executeUpdate(List<String> sqlList, List<JSONObject> paramsList) {
        String rtnStatus;
        Transaction tx = null;
        try {
            Session session = super.getBaseDao().getHibernateSession();
            boolean needCommit = true;
            tx = session.getTransaction();// 获取事务对象(调用者未启动事务时返回一个新的事务)
            if (tx.isActive()) {// 机器人节点或定时任务中,事务已启动,且结束后会自动提交事务
                needCommit = false;
            } else {// 其它情况下,事务未启动,需begin
                tx.begin();
            }
            for (int i = 0; i < sqlList.size(); i++) {
                NativeQuery query = session.createSQLQuery(sqlList.get(i));
                JSONObject params = paramsList.get(i);
                for (String paramKey : params.keySet()) {// 设置sql参数值
                    query.setParameter(paramKey, params.get(paramKey));
                }
                query.executeUpdate();
            }
            if (needCommit) {
                tx.commit();// 事务提交
            }
            rtnStatus = XpStringUtil.CODE_SUCCESS;
        } catch (Exception e) {
            assert tx != null;
            tx.rollback();// 出错回滚
            throw new RuntimeException(e);
        }
        return rtnStatus;
    }

    @Override
    public String executeUpdate(String sql, JSONObject param) {
        if (StringUtil.isNull(sql)) {
            return XpStringUtil.CODE_ERROR;
        }
        List<String> sqlList = new ArrayList<>();
        List<JSONObject> paramList = new ArrayList<>();
        sqlList.add(sql);
        paramList.add(param);
        return executeUpdate(sqlList, paramList);
    }

    @Override
    public long getQueryMaxCount(String sql, JSONObject params) {
        // query.uniqueResult(); 用不了
        sql = "SELECT COUNT(*) FROM (" + sql + ") AS count_" + IDGenerator.generateID();
        NativeQuery query = super.getBaseDao().getHibernateSession().createNativeQuery(sql);
        params.keySet().parallelStream().forEach(key -> {
            // 如果不是固定参数
            if (!"_fixed".equals(key)) {
                query.setParameter(key, params.get(key));
            }
        });
        BigInteger count = (BigInteger) query.list().get(0);
        return count.intValue();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <bean id="xpXformBaseDao"
          class="com.landray.kmss.xpcommon.dao.XpXformBaseDaoImp"
          parent="KmssBaseDao" abstract="true">
    </bean>

    <bean id="xpXformModelingModelMainBaseDao"
          class="com.landray.kmss.xpcommon.dao.XpXformModelingModelMainBaseDaoImp"
          parent="xpXformBaseDao">
    </bean>

    <bean id="xpXformModelingSimpleMainBaseDao"
          class="com.landray.kmss.xpcommon.dao.XpXformModelingSimpleMainBaseDaoImp"
          parent="xpXformBaseDao">
    </bean>

    <bean id="xpXformReviewBaseDao"
          class="com.landray.kmss.xpcommon.dao.XpXformReviewBaseDaoImp"
          parent="xpXformBaseDao">
    </bean>

    <bean id="xpSqlBaseTarget"
          class="com.landray.kmss.xpcommon.service.spring.XpSqlBaseServiceImp"
          parent="KmssBaseTarget" abstract="true">
    </bean>

    <bean id="xpSqlBaseOracleTarget"
          class="com.landray.kmss.xpcommon.service.spring.XpSqlBaseOracleServiceImp"
          parent="KmssBaseTarget" abstract="true">
    </bean>
</beans>

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <bean
            id="xpEkpSqlEkpTarget"
            class="com.landray.kmss.xp.modeling.app.it.service.spring.XpEkpSqlEkpServiceImp"
            parent="xpSqlBaseTarget">
    </bean>
    <bean
            id="xpEkpSqlErpTarget"
            class="com.landray.kmss.xp.modeling.app.it.service.spring.XpEkpSqlErpServiceImp"
            parent="xpSqlBaseOracleTarget">
    </bean>
    <bean
            id="xpEkpSqlBpmTarget"
            class="com.landray.kmss.xp.modeling.app.it.service.spring.XpEkpSqlBpmServiceImp"
            parent="xpSqlBaseOracleTarget">
    </bean>

    <bean id="xpEkpSqlDefinitionDao"
          class="com.landray.kmss.xp.modeling.app.it.dao.XpEkpSqlDefinitionDaoImp"
          parent="xpXformModelingSimpleMainBaseDao">
        <property name="tableName" value="ekp_sql_definition"/>
    </bean>
    <bean id="xpEkpSqlDefinitionTarget"
          class="com.landray.kmss.xp.modeling.app.it.service.spring.XpEkpSqlDefinitionServiceImp">
    </bean>

    <bean id="xpEkpSqlMainWsTarget"
          class="com.landray.kmss.xp.modeling.app.it.webservice.XpEkpSqlMainWsImp">
    </bean>
</beans>

3、具体实现 - action

package com.landray.kmss.xp.modeling.app.it.actions;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.landray.kmss.common.actions.ExtendAction;
import com.landray.kmss.common.service.IBaseService;
import com.landray.kmss.sys.organization.model.SysOrgElement;
import com.landray.kmss.util.DateUtil;
import com.landray.kmss.util.SpringBeanUtil;
import com.landray.kmss.util.StringUtil;
import com.landray.kmss.util.UserUtil;
import com.landray.kmss.web.action.ActionForm;
import com.landray.kmss.web.action.ActionForward;
import com.landray.kmss.web.action.ActionMapping;
import com.landray.kmss.xp.modeling.app.it.service.spring.XpEkpSqlDefinitionServiceImp;
import com.landray.kmss.xp.modeling.app.it.util.XpSqlUtil;
import com.landray.kmss.xp.util.XpRequestUtil;
import com.landray.kmss.xp.util.XpStringUtil;
import com.landray.kmss.xpcommon.service.spring.XpSqlBaseServiceImp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

import static com.landray.kmss.tic.core.common.actions.TicCoreInvokeFuncAction.ReadAsChars;

/**
 * @author liquid
 * @date 2022年10月10日
 */
public class XpEkpSqlAction extends ExtendAction {
    private static final Logger logger = LoggerFactory.getLogger(XpEkpSqlAction.class);
    private XpSqlBaseServiceImp xpEkpSqlService;
    private XpSqlBaseServiceImp xpErpSqlService;
    private XpSqlBaseServiceImp xpBpmSqlService;
    private XpEkpSqlDefinitionServiceImp xpEkpSqlDefinitionService;

    public XpSqlBaseServiceImp getXpSqlBaseService(String dbSourceName) {
        if (Objects.equals(dbSourceName, "EKP")) {
            if(xpEkpSqlService == null) {
                xpEkpSqlService = (XpSqlBaseServiceImp) SpringBeanUtil.getBean("xpEkpSqlEkpTarget");
            }
            return xpEkpSqlService;
        } else if (Objects.equals(dbSourceName, "ERP")) {
            if(xpErpSqlService == null) {
                xpErpSqlService = (XpSqlBaseServiceImp) SpringBeanUtil.getBean("xpEkpSqlErpTarget");
            }
            return xpErpSqlService;
        } else if (Objects.equals(dbSourceName, "BPM")) {
            if(xpBpmSqlService == null) {
                xpBpmSqlService = (XpSqlBaseServiceImp) SpringBeanUtil.getBean("xpEkpSqlBpmTarget");
            }
            return xpBpmSqlService;
        }
        return null;
    }

    public XpEkpSqlDefinitionServiceImp getXpEkpSqlDefinitionService() {
        if (xpEkpSqlDefinitionService == null) {
            xpEkpSqlDefinitionService = (XpEkpSqlDefinitionServiceImp) SpringBeanUtil.getBean("xpEkpSqlDefinitionTarget");
        }
        return xpEkpSqlDefinitionService;
    }

    @Override
    protected IBaseService getServiceImp(HttpServletRequest request) {
        return null;
    }

    /**
     * @apiNote 执行ekpSql获取查询结果
     * @author liquid
     * @date 2022年10月11日
     * 传入参数-
     * key ekpSql关键字
     * params 传入参数(json字符串)
     * returnType (可选:不传入则默认返回array)回传数据类型(array、json)
     * 返回参数-
     * queryData 查询结果数据
     */
    public ActionForward executeQuery(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject result = new JSONObject();
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        String bodyStr = ReadAsChars(request);
        JSONObject o = JSONObject.parseObject(bodyStr);
        String invokeDatetime = DateUtil.convertDateToString(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
        StopWatch sw = new StopWatch();

        /* 获取body参数 */
        sw.start("task_1");
        String key = o.getString("key");
        JSONObject params = JSONObject.parseObject(o.getString("params"));
        String returnType = o.getString("returnType");
        // 不传入params参数,另其为空JSONObject,避免后续空引用错误
        params = params == null ? new JSONObject() : params;
        // 参数校验
        if (StringUtil.isNull(key)) {
            XpRequestUtil.setFailure(response, "调用失败:请检查参数[名]和[值]");
            return null;
        }

        /* 业务逻辑 */
        XpEkpSqlDefinitionServiceImp xpEkpSqlDefinitionService = getXpEkpSqlDefinitionService();
        Map definitionData = xpEkpSqlDefinitionService.getSelectedColumnsByKey(key);
        if (definitionData == null || definitionData.size() == 0) {
            XpRequestUtil.setFailure(response, "调用失败:关键字错误、不存在");
            return null;
        }
        // 调用权限检查(调用XpEkpSqlServiceImp方法)
        boolean isAuthorized = xpEkpSqlDefinitionService.isAuthorized((List<SysOrgElement>) definitionData.get("fd_authorizing"), true);
        if (!isAuthorized) {
            XpRequestUtil.setFailure(response, "调用失败:该用户无权限调用");
            return null;
        }
        String sql = (String) definitionData.get("fd_sql");
        // sql参数校验
        if (!XpSqlUtil.checkSqlParamsNotCheckFixed(sql, params)) {
            XpRequestUtil.setFailure(response, "调用失败:sql与传入的参数不匹配");
            return null;
        }
        // 设置动态sql片段
        sql = XpSqlUtil.setDynamicSql(sql, params);
        // 执行sql
        String dbSource = (String) definitionData.get("fd_db_source");
        XpSqlBaseServiceImp xpSqlService = getXpSqlBaseService(dbSource);
        // erp、bpm的sql参数,JSONArray转数组
        if ("ERP".equals(dbSource) || "BPM".equals(dbSource)) {
            JSONObject finalParams = params;
            JSONObject newParams = new JSONObject();
            finalParams.keySet().forEach(paramKey -> {
                Object obj = finalParams.get(paramKey);
                if (obj instanceof JSONArray) {
                    newParams.put(paramKey, ((JSONArray) obj).toArray());
                } else {
                    newParams.put(paramKey, obj);
                }
            });
            params = newParams;
        }
        // 开始执行sql
        Object queryData;
        if (StringUtil.isNotNull(returnType) && "json".equals(returnType)) {// 返回json格式
            queryData = xpSqlService.executeQueryToMap(sql, params);
        } else {// 返回数组格式
            queryData = xpSqlService.executeQuery(sql, params);
        }
        result.put("queryData",queryData);
        result.put("queryMaxCount", xpSqlService.getQueryMaxCount(sql, params));

        /* 响应数据 */
        result.put("status", XpRequestUtil.STATUS_SUCCESS);
        result.put("code", XpRequestUtil.CODE_SUCCESS);
        result.put("msg", "调用成功");
        XpRequestUtil.setResponseResult(response, result);
        sw.stop();

        /* 后续业务逻辑 */
        // 打印输出真正执行的sql语句
        String actualSql = XpSqlUtil.getActualSql(sql, params);
        String sqlKey = (String) definitionData.get("fd_key");
        if ("Y".equals(definitionData.get("fd_print_sql"))) {
            System.out.println(sqlKey + ":" + actualSql);
        }
        // 输出调用记录日志到文件
        if ("Y".equals(definitionData.get("fd_call_record"))) {
            Map<String,Object> callRecord = new HashMap<>();
            callRecord.put("fd_key", sqlKey);
            callRecord.put("fd_invoker", UserUtil.getUser().getFdId());
            callRecord.put("fd_invoke_datetime", invokeDatetime);
            callRecord.put("fd_consuming_time", String.valueOf(sw.getTotalTimeMillis()));
            callRecord.put("fd_executed_sql", actualSql);
            logger.info("ekpSql调用记录:" + callRecord);
        }

        return null;
    }

    /**
     * @apiNote 执行ekpSql写入操作(仅支持对同一数据源进行操作)
     * @author liquid
     * @date 2023年2月6日
     * 传入参数-
     * keyOrder: sqlKey列表(以分号分隔),用以表示执行顺序
     * sqlParams: sqlParams.md
     * 返回参数-
     * updateStatus: 1 sql执行成功  0 sql执行失败
     */
    public ActionForward executeUpdate(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject result = new JSONObject();
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        String bodyStr = ReadAsChars(request);
        JSONObject o = JSONObject.parseObject(bodyStr);
        String invokeDatetime = DateUtil.convertDateToString(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
        StopWatch sw = new StopWatch();

        /* 获取body参数 */
        sw.start("task_1");
        String keyOrder = o.getString("keyOrder");
        String sqlParamsStr = o.getString("sqlParams");
        JSONObject sqlParam = JSONObject.parseObject(sqlParamsStr);
        // 不传入params参数,另其为空JSONObject,避免后续空引用错误
        sqlParam = sqlParam == null ? new JSONObject() : sqlParam;
        // 参数校验
        if (StringUtil.isNull(keyOrder) || StringUtil.isNull(sqlParamsStr)) {
            XpRequestUtil.setFailure(response, "调用失败:请检查参数[名]和[值]");
            return null;
        }

        /* 业务逻辑 */
        XpEkpSqlDefinitionServiceImp xpEkpSqlDefinitionService = getXpEkpSqlDefinitionService();
        Map<String, Map<String, Object>> definitionDataMap;
        // 关键字列表
        List<String> sqlKeyList = Arrays.stream(keyOrder.split(XpStringUtil.SEMICOLON)).distinct().collect(Collectors.toList());
        // 将关键字对应的数据拿出来
        definitionDataMap = xpEkpSqlDefinitionService.getSelectedColumnsByKeyList(sqlKeyList);
        if (definitionDataMap == null || definitionDataMap.size() == 0
                || definitionDataMap.size() != sqlKeyList.size()) {
            // 根据传入的sqlKey拿到空的sql定义,或sqlKey数量和sql定义数量不匹配
            XpRequestUtil.setFailure(response, "调用失败:关键字错误、不存在");
            return null;
        }
        // 调用权限检查(调用XpEkpSqlServiceImp方法)
        for (String sqlKey : sqlKeyList) {
            Map<String, Object> definitionData = definitionDataMap.get(sqlKey);
            if (definitionData == null) {
                continue;
            }
            boolean isAuthorized = xpEkpSqlDefinitionService.isAuthorized((List<SysOrgElement>) definitionData.get("fd_authorizing"), true);
            if (!isAuthorized) {
                XpRequestUtil.setFailure(response, "调用失败:该用户无权限调用");
                return null;
            }
        }
        // sql参数校验 & 设置动态sql片段
        for (String sqlKey : sqlKeyList) {
            String sql = (String) definitionDataMap.get(sqlKey).get("fd_sql");
            JSONArray params = sqlParam.getJSONArray(sqlKey);
            for (Object param : params) {
                // sql参数校验
                boolean isValidParam = XpSqlUtil.checkSqlParamsNotCheckFixed(sql, (JSONObject) param);
                if (!isValidParam) {
                    XpRequestUtil.setFailure(response, "调用失败:sql与传入的参数不匹配");
                    return null;
                }
                // 设置动态sql片段
                definitionDataMap.get(sqlKey).put("fd_sql", XpSqlUtil.setDynamicSql(sql, (JSONObject) param));
            }
        }
        // sql和参数
        String dbSourceName = null;
        List<String> sqlList = new ArrayList<>();
        List<JSONObject> paramsList = new ArrayList<>();
        for (String sqlKey : sqlKeyList) {
            String sql = (String) definitionDataMap.get(sqlKey).get("fd_sql");
            dbSourceName = (String) definitionDataMap.get(sqlKey).get("fd_db_source");
            JSONArray paramArr = sqlParam.getJSONArray(sqlKey);
            for (Object param : paramArr) {
                sqlList.add(sql);
                // erp、bpm的sql参数,JSONArray转数组
                if ("ERP".equals(dbSourceName) || "BPM".equals(dbSourceName)) {
                    JSONObject newParam = new JSONObject();
                    JSONObject finalParams = (JSONObject) param;
                    finalParams.keySet().forEach(paramKey -> {
                        Object obj = finalParams.get(paramKey);
                        if (obj instanceof JSONArray) {
                            newParam.put(paramKey, ((JSONArray) obj).toArray());
                        } else {
                            newParam.put(paramKey, obj);
                        }
                    });
                    paramsList.add(newParam);
                } else {
                    paramsList.add((JSONObject) param);
                }
            }
        }
        // 执行sql
        XpSqlBaseServiceImp xpSqlService = getXpSqlBaseService(dbSourceName);
        result.put("updateStatus", xpSqlService.executeUpdate(sqlList, paramsList));

        /* 响应数据 */
        result.put("status", XpRequestUtil.STATUS_SUCCESS);
        result.put("code", XpRequestUtil.CODE_SUCCESS);
        result.put("msg", "调用成功");
        XpRequestUtil.setResponseResult(response, result);
        sw.stop();

        /* 后续业务逻辑 */
        // 打印输出真正执行的sql语句
        for (String sqlKey : sqlKeyList) {
            Map<String, Object> definitionData = definitionDataMap.get(sqlKey);
            if ("Y".equals(definitionData.get("fd_print_sql"))) {
                String sql = (String) definitionData.get("fd_sql");
                JSONArray paramArr = (JSONArray) sqlParam.get(sqlKey);
                for (Object param : paramArr) {
                    System.out.println(sqlKey + ":" + XpSqlUtil.getActualSql(sql, (JSONObject) param));
                }
            }
        }
        // 输出调用记录日志到文件
        for (String sqlKey : sqlKeyList) {
            Map<String, Object> definitionData = definitionDataMap.get(sqlKey);
            if ("Y".equals(definitionData.get("fd_call_record"))) {
                String sql = (String) definitionData.get("fd_sql");
                JSONArray paramArr = (JSONArray) sqlParam.get(sqlKey);
                for (Object param : paramArr) {
                    String actualSql = XpSqlUtil.getActualSql(sql, (JSONObject) param);
                    Map<String,Object> callRecord = new HashMap<>();
                    callRecord.put("fd_key", sqlKey);
                    callRecord.put("fd_invoker", UserUtil.getUser().getFdId());
                    callRecord.put("fd_invoke_datetime", invokeDatetime);
                    callRecord.put("fd_consuming_time", String.valueOf(sw.getTotalTimeMillis()));
                    callRecord.put("fd_executed_sql", actualSql);
                    logger.info("ekpSql调用记录:" + callRecord);
                }
            }
        }

        return null;
    }
}
package com.landray.kmss.xp.modeling.app.it.actions;

import com.alibaba.fastjson.JSONObject;
import com.landray.kmss.common.actions.ExtendAction;
import com.landray.kmss.common.service.IBaseService;
import com.landray.kmss.util.SpringBeanUtil;
import com.landray.kmss.util.StringUtil;
import com.landray.kmss.web.action.ActionForm;
import com.landray.kmss.web.action.ActionForward;
import com.landray.kmss.web.action.ActionMapping;
import com.landray.kmss.xp.modeling.app.it.dao.XpEkpSqlDefinitionDaoImp;
import com.landray.kmss.xp.modeling.app.it.service.spring.XpEkpSqlDefinitionServiceImp;
import com.landray.kmss.xp.util.XpRequestUtil;
import com.landray.kmss.xp.xform.service.spring.XpXformTemplateServiceImp;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.List;
import java.util.Map;

import static com.landray.kmss.tic.core.common.actions.TicCoreInvokeFuncAction.ReadAsChars;

/**
 * @author liquid
 */
public class XpEkpSqlDefinitionAction extends ExtendAction {
    private static XpEkpSqlDefinitionServiceImp xpEkpSqlDefinitionService;
    private static XpXformTemplateServiceImp xpXformTemplateServiceImp;

    public static XpEkpSqlDefinitionServiceImp getXpEkpSqlDefinitionService() {
        if (xpEkpSqlDefinitionService == null) {
            xpEkpSqlDefinitionService = (XpEkpSqlDefinitionServiceImp) SpringBeanUtil.getBean("xpEkpSqlDefinitionTarget");
        }
        return xpEkpSqlDefinitionService;
    }

    public static XpXformTemplateServiceImp getXpXformTemplateServiceImp() {
        if (xpXformTemplateServiceImp == null) {
            xpXformTemplateServiceImp = (XpXformTemplateServiceImp) SpringBeanUtil.getBean("xpXformTemplateTarget");
        }
        return xpXformTemplateServiceImp;
    }

    @Override
    protected IBaseService getServiceImp(HttpServletRequest request) {
        return null;
    }

    /**
     * @apiNote 检查关键字唯一性
     * @author liquid
     * @date 2022年10月11日
     * 传入参数-
     * id 表单id(更新数据时不为空)
     * key 关键字
     * 返回参数-
     * unique 是否唯一
     */
    public ActionForward checkKeyUnique(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject result = new JSONObject();
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        String bodyStr = ReadAsChars(request);
        JSONObject o = JSONObject.parseObject(bodyStr);

        /* 获取body参数 */
        String id = o.getString("id");
        String key = o.getString("key");
        // 参数校验
        if (StringUtil.isNull(key)) {
            XpRequestUtil.setFailure(response, "调用失败:请检查参数[名]和[值]");
            return null;
        }

        /* 业务逻辑 */
        XpEkpSqlDefinitionServiceImp xpEkpSqlDefinitionService = getXpEkpSqlDefinitionService();
        boolean unique = xpEkpSqlDefinitionService.checkKeyUnique(id, key);
        result.put("unique", unique);

        /* 响应数据 */
        result.put("status", XpRequestUtil.STATUS_SUCCESS);
        result.put("code", XpRequestUtil.CODE_SUCCESS);
        result.put("msg", "调用成功");
        XpRequestUtil.setResponseResult(response, result);

        return null;
    }

    /**
     * @apiNote 获取开窗配置JSON字符串
     * @author liquid
     * @date 2022年11月17日
     * 传入参数-
     * key 关键字
     * 返回参数-
     * openWinConfigJson 开窗配置JSON字符串
     */
    public ActionForward getOpenWinConfigJson(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject result = new JSONObject();
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        String bodyStr = ReadAsChars(request);
        JSONObject o = JSONObject.parseObject(bodyStr);

        /* 获取body参数 */
        String key = o.getString("key");
        // 参数校验
        if (StringUtil.isNull(key)) {
            XpRequestUtil.setFailure(response, "调用失败:请检查参数[名]和[值]");
            return null;
        }

        /* 业务逻辑 */
        XpEkpSqlDefinitionServiceImp xpEkpSqlDefinitionService = getXpEkpSqlDefinitionService();
        Object[] data = (Object[]) xpEkpSqlDefinitionService.getColumnByKey(key, "fdId,fd_openwin_config_json");
        result.put("fdId", data[0]);
        result.put("openWinConfigJson", data[1]);

        /* 响应数据 */
        result.put("status", XpRequestUtil.STATUS_SUCCESS);
        result.put("code", XpRequestUtil.CODE_SUCCESS);
        result.put("msg", "调用成功");
        XpRequestUtil.setResponseResult(response, result);

        return null;
    }

    /**
     * @apiNote 获取在系统用已引用某sql的位置(最新版的xform模板信息)
     * @author liquid
     * @date 2023年2月21日
     * 传入参数-
     * key 关键字
     * 返回参数-
     * xformTemplateInfo 已引用的xform模板信息
     */
    public ActionForward getWhereCall(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject result = new JSONObject();
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        String bodyStr = ReadAsChars(request);
        JSONObject o = JSONObject.parseObject(bodyStr);

        /* 获取body参数 */
        String key = o.getString("key");
        // 参数校验
        if (StringUtil.isNull(key)) {
            XpRequestUtil.setFailure(response, "调用失败:请检查参数[名]和[值]");
            return null;
        }
        // 判断key是否存在
        XpEkpSqlDefinitionServiceImp xpEkpSqlDefinitionService = getXpEkpSqlDefinitionService();
        String definition = (String) xpEkpSqlDefinitionService.getColumnByKey(key, "fdId");
        if (definition == null) {
            XpRequestUtil.setFailure(response, "调用失败:关键字不存在");
            return null;
        }

        /* 业务逻辑 */
        XpXformTemplateServiceImp xpXformTemplateServiceImp = getXpXformTemplateServiceImp();
        List<Map<String, Object>> xformTemplateInfo1 = xpXformTemplateServiceImp.getXfromTemplateInfoByDesignerHtml("'" + key + "'");
        List<Map<String, Object>> xformTemplateInfo2 = xpXformTemplateServiceImp.getXfromTemplateInfoByDesignerHtml("&quot;" + key + "&quot;");
        xformTemplateInfo1.addAll(xformTemplateInfo2);
        result.put("xformTemplateInfo", xformTemplateInfo1);

        /* 响应数据 */
        result.put("status", XpRequestUtil.STATUS_SUCCESS);
        result.put("code", XpRequestUtil.CODE_SUCCESS);
        result.put("msg", "调用成功");
        XpRequestUtil.setResponseResult(response, result);

        return null;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean
            class="com.landray.kmss.xp.modeling.app.it.actions.XpModelingItMainAction"
            name="/xp/modeling/app/it/actions/XpModelingItMainAction.do"
            lazy-init="true"
            parent="KmssBaseAction">
    </bean>
    <bean
            class="com.landray.kmss.xp.modeling.app.it.actions.XpEkpSqlAction"
            name="/xp/modeling/app/it/actions/XpEkpSqlAction.do"
            lazy-init="true"
            parent="KmssBaseAction">
    </bean>
    <bean
            class="com.landray.kmss.xp.modeling.app.it.actions.XpEkpSqlDefinitionAction"
            name="/xp/modeling/app/it/actions/XpEkpSqlDefinitionAction.do"
            lazy-init="true"
            parent="KmssBaseAction">
    </bean>
</beans>

4、前端调用

// ekpSql调用 com.landray.kmss.xp.modeling.app.it.actions.XpEkpSqlAction.executeEkpSql
ajaxActionPms("xp/modeling/app/it/actions/XpEkpSqlAction.do?method=executeQuery", {
    key: "ekpsql_testSql001",
    params: {
        name:"黎令魁"
    }
}).then((res)=>{
    if (res.status !== "success") { errorHandler(res); return; }
    // 成功回调
    console.log(res);
}).catch((error)=>{errorHandler(error);})



// 以下函数可作为公用函数
/**
 * 调用ekp后台java方法 - promise回调方式(需返回基本数据类型时,请使用非promise方式)
 * @author liquid
 * @date 2022年6月8日
 * @param {string} path pring-mvc.xml中定义的bean.name+方法名
 * 例如:xp/org/organizational/actions/XpOrgMainAction.do?method=getFdHierarchyId
 * @param {object} data ajax.data,无需序列化
 * @return {Promise<unknown>}
 */
function ajaxActionPms(path, data) {
    return new Promise((resolve, reject) => {
        $.ajax({
            type: "POST",
            contentType:"application/json;charset=utf-8",
            url: Com_Parameter.ContextPath + path,
            data: JSON.stringify(data),
            dataType:"json",
            async: true,
            success: (res)=>{resolve(res)},
            error: (error)=>{reject(error)}
        })
    });
}

/**
 * 错误通用处理(建议在随机性错误处调用,以便开发人员排错)
 * @author liquid
 * @date 2022年5月31日
 * @param {object} obj 错误信息对象
 * @param {boolean} [isAlert=true] 是否alert相关错误信息
 * @return {void}
 */
function errorHandler(obj, isAlert) {
    isAlert = typeof isAlert === "undefined";
    const fileRow = getFileRow();
    if (isAlert) {
        alert("file: " + fileRow.file + "\nrow: " + fileRow.row + "\nmsg: " + JSON.stringify(obj));
    }
    console.log("--------------ERROR------------")
    console.log("msg", obj);
    console.log("file", fileRow.file);
    console.log("row", fileRow.row);
    console.log("--------------ERROR------------")
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liquid-Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值