BaseModel

BaseModel是后台底层架构中最重要的公共类之一,它充当MVC模式中的Model部分,它继承了JFinal Model类,可调用Model中任何公开的方法。数据库生成Model类需要继承BaseModel,此类封装了该表的增加、删除、更新、查询、分布查询、树形查询等方法。

package com.zshsoft.model.base;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import java.util.Map.Entry;

import jodd.io.FileUtil;
import jodd.util.StringUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Console;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;

import com.google.common.collect.Lists;
import com.jfinal.core.converter.TypeConverter;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.Kv;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;
import com.jfinal.plugin.ehcache.CacheKit;
import com.jfinal.plugin.ehcache.IDataLoader;
import com.zshsoft.web.constance.Constant;
import com.zshsoft.web.kit.EasyUIKit;
import com.zshsoft.web.kit.LogUtils;
import com.zshsoft.web.kit.SeqKit;
import com.zshsoft.web.kit.SessionKit;
import com.zshsoft.web.kit.ThreadLocalKit;
import com.zshsoft.web.vo.HMap;
import com.zshsoft.web.vo.PageData;

/****************************************************************
 * Model基类,封装了增加、删除、修改、分页等功能,可直接调用
 * 
 * @author 周光
 * 
 * @param <M>
 ***************************************************************/
@SuppressWarnings("serial")
public class BaseModel<M extends BaseModel<M>> extends Model<M> {
    protected static final String CACHE_SYSTEM = Constant.CACHE_SYSTEM;// 系统缓存名称
    protected static final String CACHE_URL30 = Constant.CACHE_URL30;// 30分钟缓存
    protected static final String CACHE_URL60 = Constant.CACHE_URL60;// 60分钟缓存

    protected transient Table table;

    /**
     * 映射表名 不参与序列化
     */
    private transient String tableName;

    /**
     * 是否启用自动缓存
     */
    protected transient boolean cacheEnable = true;
    protected transient int cacheTime = 60 * 60 * 24; // 1day

    /**********************************************
     * 添加数据到缓存
     * 
     * @param key
     * @param value
     */
    public void puCache(Object key, Object value) {
        CacheKit.put(CACHE_SYSTEM, key, value);
    }

    /**
     * 获取缓存中的数据
     * 
     * @param key
     * @param <T>
     * @return
     */
    public <T> T getCache(Object key) {
        return CacheKit.get(CACHE_SYSTEM, key);
    }

    /**
     * 获取缓存中的数据 , 如果缓存不存在,则通过dataloader 去加载
     * 
     * @param key
     * @param dataloader
     * @param <T>
     * @return
     */
    public <T> T getCache(Object key, IDataLoader dataloader) {
        return CacheKit.get(CACHE_SYSTEM, key, dataloader);
    }

    /**
     * 移除缓存数据
     * 
     * @param key
     */
    public void removeCache(Object key) {
        if (key == null)
            return;
        CacheKit.remove(CACHE_SYSTEM, key);
    }

    /**
     * 是否启用自动缓存
     * 
     * @param enable
     * @return
     */
    @SuppressWarnings("unchecked")
    public M cacheEnable(boolean enable) {
        this.cacheEnable = enable;
        return (M) this;
    }

    public boolean cacheEnable() {
        return cacheEnable;
    }

    /**
     * 设置默认的缓存时间
     * 
     * @param time 缓存时间,单位:秒
     * @return
     */
    @SuppressWarnings("unchecked")
    public M cacheTime(int time) {
        this.cacheTime = time;
        return (M) this;
    }

    public int cacheTime() {
        return cacheTime;
    }

    @SuppressWarnings("unchecked")
    @Override
    public M _setAttrs(Map<String, Object> attrs) {
        for (Entry<String, Object> e : attrs.entrySet()) {
            if (hasColumn(e.getKey())) {
                set(e.getKey(), e.getValue());
            }
        }
        return (M) this;
    }

    /**
     * 更新或者保存 有主键就更新,没有就保存
     * 
     * @return
     */
    public boolean saveOrUpdate() {
        Object keyObj = get(getPrimaryKey());
        if (null == keyObj || "".equals(keyObj.toString())) {
            return super.save();
        }
        return super.update();
    }

    /********************************
     * 设置其他属性
     */
    protected void putOtherAttrs() {
        if (hasColumn(Constant.MODIFIED_TIME) && get(Constant.MODIFIED_TIME) == null) {
            set(Constant.MODIFIED_TIME, new Date());
        }

        if (hasColumn(Constant.CREATE_TIME) && get(Constant.CREATE_TIME) == null) {
            set(Constant.CREATE_TIME, new Date());
        }

        if (hasColumn(Constant.OPER_ID) && get(Constant.OPER_ID) == null) {
            set(Constant.OPER_ID, SeqKit.getAID002());
        }
    }

    /*************************************************************
     * 保存表信息
     * 
     * @param attrs
     * @throws Exception
     */
    public void save(PageData pd) throws Exception {
        Record record = new Record();

        setCreater(pd);
        setModifier(pd);

        record.setColumns(pd.getMap());

        Table table = getTable();
        String pk = table.getPrimaryKey()[0];
        String tableName = table.getName();
        // record.set(pk, SeqKit.);

        pd.clear();
        pd = null;
        Db.save(tableName, pk, record);
    }

    /********************************************
     * 保存后返回主键编号
     * 
     * @return
     * @throws Exception
     */
    public Long saveReturnPK(PageData pd) throws Exception {
        Record record = new Record();
        setCreater(pd);
        setModifier(pd);
        record.setColumns(pd.getMap());
        Table table = getTable();
        String tableName = table.getName();
        String pk = table.getPrimaryKey()[0];
        // record.set(pk, SeqKit.getAID001());
        Db.save(tableName, pk, record);
        pd.clear();
        pd = null;
        return record.getLong(pk);
    }

    /*********************************************************************
     * 保存或者修改
     * 
     * @param attrs
     * @throws Exception
     */
    public void saveOrUpdate(PageData pd) throws Exception {
        boolean flag = true;// 新增标志

        Record record = new Record();

        Table table = getTable();// 获取表信息
        String tableName = table.getName();// 获取表名
        String pk = table.getPrimaryKey()[0];// 获取表主键

        Object paramPK = pd.get(pk);

        // 如果主键不为空,则为修改
        if (null != paramPK) {
            record = Db.findById(tableName, pk, paramPK);
            flag = false;// 修标志
            if (hasColumn(Constant.MODIFIED_REMARK) && StrKit.isBlank(pd.getStr(Constant.MODIFIED_REMARK))) {
                pd.set(Constant.MODIFIED_REMARK, "记录修改");
            }
        } else {
            setCreater(pd);
        }

        setModifier(pd);

        try {
            record.setColumns(pd.getMap());// 填充属性
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("填充属性出错:" + e.getMessage());
        }

        if (flag) {
            // record.set(pk, SeqKit.getAID001());
            Db.save(tableName, pk, record);
        } else {
            Db.update(tableName, pk, record);
        }
    }

    /********************************
     * 更新
     */
    public void update(PageData pd) throws Exception {
        Table table = getTable();// 获取表信息
        String tableName = table.getName();// 获取表名
        String pk = table.getPrimaryKey()[0];// 获取表主键
        Object paramPK = pd.get(pk);
        Record record = Db.findById(tableName, pk, paramPK);
        setModifier(pd);
        record.setColumns(pd.getMap());// 填充属性
        Db.update(tableName, pk, record);
    }

    /**
     * 批量保存
     * 
     * @param data
     * @param batchSize
     * @return
     */
    public int[] batchSave(List<M> data, int batchSize) {
        if (data == null || data.size() == 0) {
            return null;
        }
        return Db.batchSave(data, batchSize);
    }

    /***************************************************
     * 批量保存,默认50条记录提交一次
     * 
     * @param data
     * @return
     */
    public int[] batchSave(List<M> data) {
        return this.batchSave(data, 50);
    }

    /***************************************************
     * 批量更改,默认50条记录提交一次
     * 
     * @param data
     * @return
     */
    public int[] batchUpdate(List<M> data) {
        if (data == null || data.size() == 0) {
            return null;
        }
        return Db.batchUpdate(data, 500);
    }

    /****************************************************
     * 根据ID来删除
     * 
     * @param ids
     * @throws Exception
     */
    public void deleteByIds(String ids) throws Exception {
        String sql = "DELETE FROM {0} WHERE {1} in ({2})";
        sql = MessageFormat.format(sql, getTableName(), getPrimaryKey(), ids);
        Db.update(sql);
    }

    /****************************************************
     * 根据ID数组来删除
     * 
     * @param ids
     * @throws Exception
     */
    public void deleteByIds(String[] ids) throws Exception {
        deleteByIds(StringUtil.join(ids, ","));
    }

    /*******************************************************************
     * 从表中获取一条记录
     * 
     * @param table      表或者视图表
     * @param conditions 后台封装的条件
     * @param fields     查询的字段
     * @return
     * @throws Exception
     */
    public M doFindFirst(String table, Kv conditions, String... fields) throws Exception {
        String sql = "select {0} from {1} where 1=1 {2} limit 1";
        String where = "";

        for (Object key : conditions.keySet()) {
            where += " and " + key.toString() + "=?";
        }

        Object[] params = conditions.values().toArray();

        if (fields == null || fields.length == 0) {
            sql = MessageFormat.format(sql, "*", table, where);
        } else {
            String strFields = StringUtil.join(fields, ",");
            sql = MessageFormat.format(sql, strFields, table, where);
        }

        // 用完之后清除缓存
        conditions.clear();
        conditions = null;
        return findFirst(sql, params);
    }

    /************************************************************************
     * 从表中获取一条记录
     * 
     * @param conditions 后台封装的条件
     * @param fields     查询的字段
     * @return
     * @throws Exception
     */
    public M doFindFirst(Kv conditions, String... fields) throws Exception {
        return doFindFirst(getTableName(), conditions, fields);
    }

    /****************************************************************
     * 获取一条记录
     * 
     * @param table  表或者视图名称
     * @param pd     前台封装的参保
     * @param fields 查询的字段名
     * @return
     * @throws Exception
     */
    public M doFindFirst(String table, PageData pd, String... fields) throws Exception {
        return doFindFirst(table, pd.kv(), fields);
    }

    /****************************************************************
     * 获取一条记录
     * 
     * @param pd     前台封装的参保
     * @param fields 查询的字段名
     * @return
     * @throws Exception
     */
    public M doFindFirst(PageData pd, String... fields) throws Exception {
        return doFindFirst(getTableName(), pd.kv(), fields);
    }

    public M doFindFirst(String... fields) throws Exception {
        return doFindFirst(Kv.create(), fields);
    }

    /**************************************************************************
     * 从表或者视图中查找一要记录,并将数据缓存
     * 
     * @param table
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public M doFindFirstByCache(String table, Ret conditions, String... fields) throws Exception {
        String sql = "select {0} from {1} where 1=1 {2} limit 1";
        String where = "";

        for (Object key : conditions.keySet()) {
            where += " and " + key.toString() + "=?";
        }

        Object[] params = conditions.values().toArray();

        if (fields == null || fields.length == 0) {
            sql = MessageFormat.format(sql, "*", table, where);
        } else {
            String strFields = StringUtil.join(fields, ",");
            sql = MessageFormat.format(sql, strFields, table, where);
        }
        // 用完之后清除缓存
        conditions.clear();
        conditions = null;
        return findFirstByCache(CACHE_SYSTEM, table + "_first", sql, params);
    }

    /*************************************************************
     * 获取一条记录并缓存
     * 
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public M doFindFirstByCache(Ret conditions, String... fields) throws Exception {
        return doFindFirstByCache(getTableName(), conditions, fields);
    }

    /***********************************************************************
     * 获取一条记录并缓存
     * 
     * @param table
     * @param pd
     * @param fields
     * @return
     * @throws Exception
     */
    public M doFindFirstByCache(String table, PageData pd, String... fields) throws Exception {
        return doFindFirstByCache(table, pd.ret(), fields);
    }

    public M doFindFirstByCache(String... fields) throws Exception {
        return doFindFirstByCache(Ret.create(), fields);
    }

    /****************************************************************************
     * 获取一条记录并缓存
     * 
     * @param pd
     * @param fields
     * @return
     * @throws Exception
     */
    public M doFindFirstByCache(PageData pd, String... fields) throws Exception {
        return doFindFirstByCache(getTableName(), pd.ret(), fields);
    }

    /**********************************************************************
     * 查询表记录数
     * 
     * @param table
     * @param conditions
     * @return
     * @throws Exception
     */
    public long doFindCount(String table, Ret conditions) throws Exception {
        String sql = "select count(1) from {0} where 1=1 {1}";
        String where = "";

        for (Object key : conditions.keySet()) {
            where += " and " + key.toString() + "=?";
        }

        Object[] params = conditions.values().toArray();

        sql = MessageFormat.format(sql, table, where);
        // 用完之后清除缓存
        conditions.clear();
        conditions = null;
        return Db.queryLong(sql, params);
    }

    /*********************************************************
     * 查询表记录数
     * 
     * @param conditions
     * @return
     * @throws Exception
     */
    public long doFindCount(Ret conditions) throws Exception {
        return doFindCount(getTableName(), conditions);
    }

    /*********************************************************
     * 查询表记录数
     * 
     * @return
     * @throws Exception
     */
    public long doFindCount() throws Exception {
        return doFindCount(getTableName(), null);
    }

    /*******************************************************************
     * 数据列表
     * 
     * @param table
     * @param orderBy
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forList(String table, String orderBy, Kv conditions, String... fields) throws Exception {
        String sql = "select {0} from {1} where 1=1 {2} {3} order by {4}";
        String where = "";

        String likes = conditions.getStr("likes");
        String keys = conditions.getStr("keys");
        // 删除模糊搜索关键词
        conditions.remove("likes");
        conditions.remove("keys");

        String or = "";
        // 封装模糊搜索
        if (StrKit.notBlank(likes)) {
            if (StrKit.notBlank(keys)) {
                keys = keys.toUpperCase();
                or += " AND (";
                String[] listLikes = likes.split(",");
                for (int i = 0; i < listLikes.length; i++) {
                    String str = listLikes[i];
                    or = or + str + " LIKE '%" + keys + "%'";
                    if (i < listLikes.length - 1) {
                        or = or + " OR ";
                    }
                }

                or += ")";
            }
        }

        String limit = conditions.getStr("limit");
        conditions.remove("limit");

        // in搜索,拼接in语句
        // 前台传格式:in:"BKC021:21,22,23"
        // 或者:in=BKC021:21,22,23
        String in = conditions.getStr("in");
        conditions.remove("in");

        // 排序的字段
        String sort = conditions.getStr("sort");
        conditions.remove("sort");

        for (Object key : conditions.keySet()) {
            where += " and " + key.toString() + "=?";
        }

        if (StrKit.notBlank(in)) {
            String[] ins = in.split(":");// 拆分出需要in的字段,使用英文冒号
            String c = ins[0];
            String v = ins[1];
            if (StrKit.notBlank(c) && StrKit.notBlank(v)) {
                String inStr = " and " + c + " IN (";
                String[] vs = v.split(",");// 拆分出in的值
                boolean isFirst = true;
                for (String s : vs) {
                    if (isFirst) {
                        isFirst = false;
                    } else {
                        inStr += ",";
                    }
                    inStr += "'" + s + "'";
                }

                inStr += ")";
                where += inStr;
            }
        }

        if (StrKit.isBlank(orderBy)) {
            orderBy = StringUtil.join(getPrimaryKeys(), ",") + " desc";
        } else {
            if (StrKit.notBlank(sort)) {
                orderBy = sort;
            }
        }

        if (StrKit.notBlank(limit)) {
            orderBy += " limit " + limit;
        }

        Object[] params = conditions.values().toArray();

        if (fields == null || fields.length == 0) {
            sql = MessageFormat.format(sql, "*", table, where, or, orderBy);
        } else {
            String strFields = StringUtil.join(fields, ",");
            sql = MessageFormat.format(sql, strFields, table, where, or, orderBy);
        }
        return find(sql, params);
    }

    /***********************************************************************
     * 获取从表可查询数据
     * 
     * @param orderBy
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forList(String orderBy, Kv conditions, String... fields) throws Exception {
        return forList(getTableName(), orderBy, conditions, fields);
    }

    /**************************************************************************
     * 默认从表中查询数据,并按主键倒序排序
     * 
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forList(Kv conditions, String... fields) throws Exception {
        return forList(getTableName(), getPrimaryKey() + " desc", conditions, fields);
    }

    /*********************************************************
     * 查询该表所有字段
     * 
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forList(String... fields) throws Exception {
        return forList(Kv.create(), fields);
    }

    /***********************************************************************
     * 获取从表可查询数据
     * 
     * @param orderBy
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forList(String orderBy, PageData pd, String... fields) throws Exception {
        return forList(getTableName(), orderBy, pd.kv(), fields);
    }

    /**************************************************************************
     * 默认从表中查询数据,并按主键倒序排序
     * 
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forList(PageData pd, String... fields) throws Exception {
        return forList(getTableName(), getPrimaryKey() + " desc", pd.kv(), fields);
    }

    /*********************************************************************
     * 从视图中查询记录
     * 
     * @param view
     * @param orderBy
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forListView(String view, String orderBy, Kv conditions, String... fields) throws Exception {
        return forList(view, orderBy, conditions, fields);
    }

    public List<M> forListView(String orderBy, Kv conditions, String... fields) throws Exception {
        return forList("v_" + getTableName(), orderBy, conditions, fields);
    }

    public List<M> forListView(Kv conditions, String... fields) throws Exception {
        return forListView(getPrimaryKey() + " desc", conditions, fields);
    }

    public List<M> forListView(String... fields) throws Exception {
        return forListView(Kv.create(), fields);
    }

    public List<M> forListView(String view, String orderBy, PageData pd, String... fields) throws Exception {
        return forList(view, orderBy, pd.kv(), fields);
    }

    public List<M> forListView(String orderBy, PageData pd, String... fields) throws Exception {
        return forList("v_" + getTableName(), orderBy, pd.kv(), fields);
    }

    public List<M> forListView(PageData pd, String... fields) throws Exception {
        return forListView(getPrimaryKey() + " desc", pd.kv(), fields);
    }

    /***************************************************************************
     * 查询数据列表,并缓存数据到cacheName中
     * 
     * @param cacheName
     * @param table
     * @param orderBy
     * @param conditions
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forListByCache(String cacheName, String table, String orderBy, Ret conditions, String... fields)
            throws Exception {
        String sql = "select {0} from {1} where 1=1 {2} order by {3}";
        String where = "";

        String limit = conditions.getStr("limit");
        conditions.remove("limit");

        for (Object key : conditions.keySet()) {
            where += " and " + key.toString() + "=?";
        }

        if (StrKit.notBlank(limit)) {
            where += " and rownum<=" + limit;
        }

        Object[] params = conditions.values().toArray();

        if (StrKit.isBlank(orderBy)) {
            orderBy = StringUtil.join(getPrimaryKeys(), ",") + " desc";
        }

        if (fields == null || fields.length == 0) {
            sql = MessageFormat.format(sql, "*", table, where, orderBy);
        } else {
            String strFields = StringUtil.join(fields, ",");
            sql = MessageFormat.format(sql, strFields, table, where, orderBy);
        }

        // 用完之后清除缓存
        conditions.clear();
        conditions = null;
        return findByCache(cacheName, cacheName + ":list:" + table, sql, params);
    }

    public List<M> forListByCache(String cacheName, String orderBy, Ret conditions, String... fields) throws Exception {
        return forListByCache(cacheName, getTableName(), orderBy, conditions, fields);
    }

    public List<M> forListByCache(String cacheName, Ret conditions, String... fields) throws Exception {
        return forListByCache(cacheName, getPrimaryKey() + " desc", conditions, fields);
    }

    public List<M> forListByCache(String cacheName, String... fields) throws Exception {
        return forListByCache(cacheName, getPrimaryKey() + " desc", Ret.create(), fields);
    }

    /*************************************************************************
     * 系统缓存数据,只要服务器不重启,数据都不会改变
     * 
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forListBySystemCache(String... fields) throws Exception {
        return forListByCache(CACHE_SYSTEM, getPrimaryKey() + " desc", Ret.create(), fields);
    }

    /********************************************************************
     * 30分钟缓存数据,每30分钟刷新一次数据
     * 
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forListByCache30(String... fields) throws Exception {
        return forListByCache(CACHE_URL30, getPrimaryKey() + " desc", Ret.create(), fields);
    }

    public List<M> forListByCache(String cacheName, String table, String orderBy, PageData pd, String... fields)
            throws Exception {
        return forListByCache(cacheName, table, orderBy, pd.ret(), fields);
    }

    public List<M> forListByCache(String cacheName, String orderBy, PageData pd, String... fields) throws Exception {
        return forListByCache(cacheName, getTableName(), orderBy, pd.ret(), fields);
    }

    public List<M> forListByCache(String cacheName, PageData pd, String... fields) throws Exception {
        return forListByCache(cacheName, getPrimaryKey() + " desc", pd.ret(), fields);
    }

    /**********************************************************************
     * 表格树
     * 
     * @param parentIdFieldName 父字段名称
     * @param textFieldName     显示值名称
     * @return
     * @throws Exception
     */
    public List<M> tree(String parentIdFieldName, String textFieldName, Object rootIdValue, String orderColumn,
            String iconColumn) throws Exception {
        String sql = "select a.*,(select count(1) from {0} where {1}=a.{2}) CHILDREN_CNT_COUNT from {0} a where 1=1  order by "
                + orderColumn;

        sql = MessageFormat.format(sql, getTableName(), parentIdFieldName, getPrimaryKey());

        List<M> list = find(sql);
        return EasyUIKit.toTree(list, getPrimaryKey(), parentIdFieldName, textFieldName, iconColumn,
                "CHILDREN_CNT_COUNT", rootIdValue);
    }

    /*******************************************
     * 树表格,默认显示值名称为name,父ID为pid
     * 
     * @return
     * @throws Exception
     */
    public List<M> tree(Object rootIdValue, String orderColumn, String iconColumn) throws Exception {
        return tree("pid", "name", rootIdValue, orderColumn, iconColumn);
    }

    /*******************************************************************************************************************
     * 有条件的查询树
     * 
     * @param kv
     * @param parentIdFieldName
     * @param textFieldName
     * @param iconColumn
     * @param rootIdValue
     * @param fields
     * @return
     * @throws Exception
     */
    public List<M> forTree(PageData pd, String... fields) throws Exception {
        String pidName = pd.getStr("pidName", "pid");
        String textName = pd.getStr("textName", "name").toString();
        String iconName = pd.getStr("iconName", "icon").toString();
        Object rootIdValue = pd.get("rootIdValue", 0);
        pd.remove("pidName");
        pd.remove("iconName");
        pd.remove("textName");
        pd.remove("rootIdValue");

        List<M> list = forList(pd, fields);
        return EasyUIKit.toTree(list, getPrimaryKey(), pidName, textName, iconName, "", rootIdValue);
    }

    /******************************************************************
     * 通用分页查询
     * 
     * @param pd
     * @param tableOrView
     * @param order
     * @param fields
     * @return
     */
    public HMap forPager(PageData pd, String tableOrView, String order, String... fields) throws Exception {
        Page<M> page = forPaginate(pd, tableOrView, order, fields);
        HMap map = new HMap();
        map.put(Constant.TOTAL, page.getTotalRow());
        map.put(Constant.ROWS, page.getList());
        pd.clear();
        pd = null;
        return map;
    }

    public Page<M> forPaginate(PageData pd, String tableOrView, String order, String... fields) throws Exception {
        // 为了兼容DataGrid分页与前台自定义分页
        // page:Datagrid分页参数;
        // pagesize:Datagrid分页参数
        // currPage:前台分页参数
        // pageSize:前台分页参数
        // limit:layui分页
        int pageNumber = pd.getInt(Constant.PAGE, pd.getInt("currPage", 1));
        int pageSize = pd.getInt(Constant.PAGESIZE, pd.getInt("pageSize", pd.getInt("limit", 40)));

        String select = "select ";
        if (fields == null || fields.length == 0) {
            select += "*";
        } else {
            select += StringUtil.join(fields, ",");
        }

        String from = "from " + tableOrView + " where 1=1 ";

        // 删除分页标志
        pd.remove(Constant.PAGE);
        pd.remove(Constant.PAGESIZE);
        pd.remove(Constant.ROWS);
        pd.remove("currPage");
        pd.remove("pageSize");
        pd.remove("_");
        if (pd.containsKey("limit")) {
            pd.remove("limit");
        }

        String likes = pd.getStr("likes");
        String keys = pd.getStr("keys");
        // 删除模糊搜索关键词
        pd.remove("likes");
        pd.remove("keys");

        // in搜索,拼接in语句
        // 前台传格式:in:"BKC021:21,22,23"
        // 或者:in=BKC021:21,22,23
        String in = pd.getStr("in");
        pd.remove("in");

        String sort = pd.getStr("sort", "");
        pd.remove("sort");

        String or = "";
        // 封装模糊搜索
        if (StrKit.notBlank(likes)) {
            if (StrKit.notBlank(keys)) {
                or += " AND (";
                String[] listLikes = likes.split(",");
                for (int i = 0; i < listLikes.length; i++) {
                    String str = listLikes[i];
                    or = or + str + " LIKE '%" + keys + "%'";
                    if (i < listLikes.length - 1) {
                        or = or + " OR ";
                    }
                }

                or += ")";
            }
        }

        from += or;

        if (StrKit.notBlank(in)) {
            String[] ins = in.split(":");// 拆分出需要in的字段,使用英文冒号
            if (ins.length > 1) {
                String c = ins[0];
                String v = ins[1];
                if (StrKit.notBlank(c) && StrKit.notBlank(v)) {
                    String inStr = " and " + c + " IN (";
                    String[] vs = v.split(",");// 拆分出in的值
                    boolean isFirst = true;
                    for (String s : vs) {
                        if (isFirst) {
                            isFirst = false;
                        } else {
                            inStr += ",";
                        }
                        inStr += "'" + s + "'";
                    }

                    inStr += ")";
                    from += inStr;
                }
            }
        }

        String and = pd.getStr("and");
        if (StrKit.notBlank(and)) {
            pd.remove("and");
            if (and.trim().toLowerCase().startsWith("and")) {
                from += " (" + and + ") ";
            } else {
                from += " and (" + and + ") ";
            }
        }

        Map<String, Object> mapObj = pd.getMap();
        Iterator<Map.Entry<String, Object>> entries = mapObj.entrySet().iterator();
        List<Object> listParams = Lists.newArrayList();
        while (entries.hasNext()) {
            Entry<String, Object> entry = entries.next();
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value == null || value.toString() == "") {
                continue;
            }

            from += " and " + key + " = ? ";
            listParams.add(value);
        }

        Object[] params = listParams.toArray();

        String orderBy = " order by ";
        if (StrKit.isBlank(order)) {
            String[] pk = getPrimaryKeys();
            orderBy += StringUtils.join(pk, ",") + " desc";
        } else {
            orderBy += sort + " " + order;
        }

        from += orderBy;

        Page<M> page = paginate(pageNumber, pageSize, select, from, params);
        return page;
    }

    public Page<M> forPaginate(String order, PageData pd, String... fields) throws Exception {
        return forPaginate(pd, getTableName(), order, fields);
    }

    public Page<M> forPaginate(PageData pd, String... fields) throws Exception {
        return forPaginate(pd, getTableName(), getPrimaryKey() + " desc", fields);
    }

    /*********************************************************************************************
     * 分页查询,从视图查询,返回Page<M>
     * 
     * @Description TODO
     * @author 周光
     * @param pd
     * @param order
     * @param fields
     * @return
     * @throws Exception Page<M>
     */
    public Page<M> forPaginateView(String order, PageData pd, String... fields) throws Exception {
        return forPaginate(pd, "v_" + getTableName(), order, fields);
    }

    /*******************************************************************************
     * 分页查询,从视图查询,返回Page<M>
     * 
     * @Description TODO
     * @author 周光
     * @param pd
     * @param fields
     * @return
     * @throws Exception Page<M>
     */
    public Page<M> forPaginateView(PageData pd, String... fields) throws Exception {
        return forPaginateView(getPrimaryKey() + " desc", pd, fields);
    }

    public HMap forPager(PageData pd, String order, String... fields) throws Exception {
        return forPager(pd, getTableName(), order, fields);
    }

    public HMap forPager(PageData pd, String... fields) throws Exception {
        return forPager(pd, getTableName(), getPrimaryKey() + " desc", fields);
    }

    public HMap forPager(String... fields) throws Exception {
        return forPager(null, getTableName(), getPrimaryKey() + " desc", fields);
    }

    public HMap forPagerView(PageData pd, String order, String... fields) throws Exception {
        return forPager(pd, "v_" + getTableName(), order, fields);
    }

    public HMap forPagerView(PageData pd, String... fields) throws Exception {
        return forPager(pd, getPrimaryKey() + " desc", fields);
    }

    public HMap forPagerView(String... fields) throws Exception {
        return forPager(null, fields);
    }

    public HMap paginate(boolean isView) throws Exception {
        return isView ? forPagerView() : forPager();
    }

    public HMap paginate() throws Exception {
        return forPager();
    }

    /**************************
     * 添加事件
     * 
     * @return
     */
    public String addAction() {
        return getTableName() + ":add";
    }

    /****************************
     * 删除事件
     * 
     * @return
     */
    public String deleteAction() {
        return getTableName() + ":delete";
    }

    /***************************
     * 更新事件
     * 
     * @return
     */
    public String updateAction() {
        return getTableName() + ":update";
    }

    /**
     * 得到映射表
     */
    public Table getTable() {
        return getTable(false);
    }

    /*****************************
     * 获取表名
     * 
     * @return
     */
    public Table getTable(boolean validateNull) {
        if (table == null) {
            table = super._getTable();
            if (table == null && validateNull) {
                String msg = String.format(
                        "class %s can not mapping to database table,maybe application cannot connect to database. ",
                        _getUsefulClass().getName());
                throw new RuntimeException(msg);
            }
        }
        return table;
    }

    /*****************************
     * 获取表名
     * 
     * @return
     */
    protected String getTableName() {
        if (tableName == null) {
            tableName = getTable(true).getName();
        }
        return tableName;
    }

    private transient String primaryKey;

    /********************************
     * 获取主键
     * 
     * @return
     */
    public String getPrimaryKey() {
        if (primaryKey != null) {
            return primaryKey;
        }
        String[] primaryKeys = getPrimaryKeys();
        if (null != primaryKeys && primaryKeys.length == 1) {
            primaryKey = primaryKeys[0];
        }
        return primaryKey;
    }

    private transient Class<?> primaryType;

    protected Class<?> getPrimaryType() {
        if (primaryType == null) {
            primaryType = TableMapping.me().getTable(_getUsefulClass()).getColumnType(getPrimaryKey());
        }
        return primaryType;
    }

    protected String[] getPrimaryKeys() {
        Table t = TableMapping.me().getTable(_getUsefulClass());
        if (t == null) {
            throw new RuntimeException("can't get table of " + _getUsefulClass() + " , maybe jboot install incorrect");
        }
        return t.getPrimaryKey();
    }

    public boolean hasColumn(String columnLabel) {
        return TableMapping.me().getTable(_getUsefulClass()).hasColumnLabel(columnLabel);
    }

    /**************************************************************************
     * 写JSON文件
     * 
     * @param obj
     * @param fileName
     * @throws IOException
     */
    public void buildJsonFile(Object obj, String fileName) throws IOException {
        String path = PathKit.getWebRootPath() + "/eapdomain/data/";
        String data = JsonKit.toJson(obj);
        FileUtil.writeString(path + fileName, data);
    }

    @SuppressWarnings("unchecked")
    public List<M> jsonToModelList(String strJson) throws Exception {
        if (StrKit.isBlank(strJson)) {
            return null;
        }
        // 转化JSON对象列表
        JSONArray array = JSONUtil.parseArray(strJson);
        List<M> list = new ArrayList<M>();

        Table table = getTable();
        // 得到属性类型的map
        Map<String, Class<?>> typeMap = table.getColumnTypeMap();
        TypeConverter converter = TypeConverter.me();
        Set<Entry<String, Class<?>>> enterSet = typeMap.entrySet();
        for (int i = 0; i < array.size(); i++) {
            M model = (M) getClass().newInstance();
            JSONObject object = array.getJSONObject(i);
            for (Entry<String, Class<?>> e : enterSet) {
                String attr = e.getKey();
                Class<?> colType = table.getColumnType(attr);
                if (object.containsKey(attr)) {
                    String paraValue = object.getStr(attr);
                    try {
                        Object value = StrKit.notBlank(paraValue) ? converter.convert(colType, paraValue) : null;
                        model.set(attr, value);
                    } catch (Exception e2) {
                        Console.error("[" + paraValue + "]转换错误:" + e2.getMessage());
                        model.set(attr, null);
                    }
                }
            }
            list.add(model);
        }
        return list;
    }

    /*******************************************************
     * 类型自动转换
     * 
     * @param strJson
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public M jsonToModel(String strJson) throws Exception {
        if (StrKit.isBlank(strJson)) {
            return null;
        }
        M model = (M) _getUsefulClass().newInstance();
        JSONObject object = JSONUtil.parseObj(strJson);
        Table table = getTable();
        // 得到属性类型的map
        Map<String, Class<?>> typeMap = table.getColumnTypeMap();
        Set<Entry<String, Class<?>>> enterSet = typeMap.entrySet();
        String attr = null;
        TypeConverter converter = TypeConverter.me();
        for (Entry<String, Class<?>> e : enterSet) {
            attr = e.getKey();
            Class<?> colType = table.getColumnType(attr);
            if (object.containsKey(attr)) {
                String paraValue = object.getStr(attr);
                try {
                    Object value = StrKit.notBlank(paraValue) ? converter.convert(colType, paraValue) : null;
                    model.set(attr, value);
                } catch (Exception e2) {
                    Console.error("[" + paraValue + "]转换错误:" + e2.getMessage());
                    model.set(attr, null);
                }

            }
        }

        return model;
    }

    /********************************************************
     * 保留小数点
     * 
     * @param attr
     * @param scale
     * @return
     */
    public BigDecimal getBigDecimal(String attr, int scale) {
        BigDecimal b = getBigDecimal(attr);
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP);
    }

    /*****************************************************************
     * 有默认值
     * 
     * @param attr
     * @param detaultValue
     * @return
     */
    public BigDecimal getBigDecimal(String attr, String detaultValue) {
        BigDecimal b = getBigDecimal(attr);
        if (null == b) {
            return new BigDecimal(detaultValue);
        }
        return b;
    }

    protected int getPageNumber() {
        Object obj = ThreadLocalKit.get(Constant.PAGE);
        int offset = Integer.parseInt(obj.toString());
        if (offset == 0) {
            return 1;
        }
        return offset;
    }

    /*********************************
     * 前台分页页数
     * 
     * @return
     */
    protected int getFontPageNumber() {
        Object obj = ThreadLocalKit.get(Constant.P);
        int p = Integer.parseInt(obj.toString());
        if (p == 0) {
            return 1;
        }
        return p;
    }

    protected int getPageSize() {
        Object obj = ThreadLocalKit.get(Constant.PAGESIZE);
        int pageSize = Integer.parseInt(obj.toString());
        return pageSize;
    }

    /******************************************************
     * 设置创建者、创建时间、创建备注
     * 
     * @param pd
     * @throws Exception
     */
    private void setCreater(PageData pd) throws Exception {
        HMap map = SessionKit.getLoginSession();

        if (hasColumn(Constant.CREATER) && pd.get(Constant.CREATER) == null) {
            pd.set(Constant.CREATER, map.getStr(Constant.UNAME));
        }

        if (hasColumn(Constant.CREATE_TIME) && pd.get(Constant.CREATE_TIME) == null) {
            pd.set(Constant.CREATE_TIME, DateTime.now());
        }

        if (hasColumn(Constant.CREATE_REMART) && pd.get(Constant.CREATE_REMART) == null) {
            pd.set(Constant.CREATE_REMART, "记录新增");
        }
    }

    /*******************************************************
     * 设置经办人、经办时间、经办备注
     * 
     * @throws Exception
     */
    private void setModifier(PageData pd) throws Exception {
        HMap map = SessionKit.getLoginSession();
        if (hasColumn(Constant.MODIFIER) && pd.get(Constant.MODIFIER) == null) {
            pd.set(Constant.MODIFIER, map.getStr(Constant.UNAME));
        }

        if (hasColumn(Constant.MODIFIED_TIME) && pd.get(Constant.MODIFIED_TIME) == null) {
            pd.set(Constant.MODIFIED_TIME, DateTime.now());
        }

        if (hasColumn(Constant.MODIFIED_REMARK) && pd.get(Constant.MODIFIED_REMARK) == null) {
            pd.set(Constant.MODIFIED_REMARK, "记录修改");
        }

        if (hasColumn(Constant.OPER_ID) && pd.get(Constant.OPER_ID) == null) {
            pd.set(Constant.OPER_ID, SeqKit.getAID002());
        }
    }

    public HMap paginateBySql(String select, String sql, Object... params) throws Exception {
        Page<M> page = paginate(getPageNumber(), getPageSize(), select, sql, params);
        HMap map = new HMap();
        map.put(Constant.TOTAL, page.getTotalRow());
        map.put(Constant.ROWS, page.getList());

        return map;
    }

    public HMap paginateBySql(String sql, Object... params) throws Exception {
        Page<M> page = paginate(getPageNumber(), getPageSize(), "SELECT *", sql, params);
        HMap map = new HMap();
        map.put(Constant.TOTAL, page.getTotalRow());
        map.put(Constant.ROWS, page.getList());

        return map;
    }

    public HMap paginateBySqlPara(String key, Kv kv) throws Exception {
        SqlPara sqlPara = getSqlPara(key, kv);
        Page<M> page = paginate(getPageNumber(), getPageSize(), sqlPara);
        HMap map = new HMap();
        map.put(Constant.TOTAL, page.getTotalRow());
        map.put(Constant.ROWS, page.getList());

        return map;
    }

    /*********************************************************************************************************
     * 返回Layui DataGrid/table的数据格式
     * 
     * @param tableOrView
     * @param order
     * @param pd
     * @param fields
     * @return
     * @throws Exception
     */
    public HMap forLayPage(String tableOrView, String order, PageData pd, String... fields) throws Exception {
        int limit = pd.getInt("limit", 0);
        int count = 0;
        List<?> data = Lists.newArrayList();
        if (limit > 0) {
            LogUtils.NORMAL.info("分页标志limit不为空:" + limit + ",执行forPaginate方法");
            Page<M> page = forPaginate(pd, tableOrView, order, fields);
            count = page.getTotalRow();
            data = page.getList();
        } else {
            LogUtils.NORMAL.info("分页标志limit为空,执行forList方法");
            if (pd.containsKey("page")) {
                pd.remove("page");
            }

            if (pd.containsKey("limit")) {
                pd.remove("limit");
            }
            data = forList(tableOrView, order, pd.kv(), fields);
            count = CollectionUtil.isEmpty(data) ? 0 : data.size();
        }

        HMap map = new HMap();
        map.put("code", 0);
        map.put("msg", "ok");
        map.put("count", count);
        map.put("data", data);

        return map;
    }

    /**
     * 返回Layui DataGrid/table的数据格式
     * 
     * @param order
     * @param pd
     * @param fields
     * @return
     * @throws Exception
     */
    public HMap forLayPage(String order, PageData pd, String... fields) throws Exception {
        return forLayPage(getTableName(), order, pd, fields);
    }

    /**
     * 返回Layui DataGrid/table的数据格式
     * 
     * @param order
     * @param pd
     * @param fields
     * @return
     * @throws Exception
     */
    public HMap forLayPageView(String order, PageData pd, String... fields) throws Exception {
        return forLayPage("v_" + getTableName(), order, pd, fields);
    }

    /**
     * 返回Layui DataGrid/table的数据格式,不分页
     * 
     * @param tableOrView
     * @param order
     * @param kv
     * @param fields
     * @return
     * @throws Exception
     */
    public HMap forLayList(String tableOrView, String order, Kv kv, String... fields) throws Exception {
        List<M> data = forList(tableOrView, order, kv, fields);
        HMap map = new HMap();
        map.put("code", 0);
        map.put("msg", "ok");
        map.put("count", data == null ? 0 : data.size());
        map.put("data", data);
        return map;
    }

    /**
     * 返回Layui DataGrid/table的数据格式,不分页
     * 
     * @param order
     * @param kv
     * @param fields
     * @return
     * @throws Exception
     */
    public HMap forLayList(String order, Kv kv, String... fields) throws Exception {
        return forLayList(getTableName(), order, kv, fields);
    }

    /**
     * 返回Layui DataGrid/table的数据格式,不分页
     * 
     * @param order
     * @param kv
     * @param fields
     * @return
     * @throws Exception
     */
    public HMap forLayListView(String order, Kv kv, String... fields) throws Exception {
        return forLayList("v_" + getTableName(), order, kv, fields);
    }

    /**
     * 设置子关联数据
     * 
     * @param items
     */
    public void putItems(List<?> items) {
        if (items != null && items.size() > 0) {
            put("items", items);
        }
    }

    /**
     * 得到关联子数据
     * 
     * @return
     */
    public <T> List<M> getItems() {
        return this.get("items");
    }
}
文档更新时间: 2020-06-30 16:13   作者:周光