public class ContextBeanHolder {
    private static ThreadLocal<HashSet<String>> lazyContext = new ThreadLocal<HashSet<String>>();
    private static ThreadLocal<Map<String, Object>> sqlParams = new ThreadLocal<Map<String, Object>>();

    /**
     * 添加排除懒加载字段
     * 
     * @param prop
     *            字段
     */
    public static void addNotLazyLoad(String prop) {
        HashSet<String> propSet = lazyContext.get();
        if (propSet == null) {
            propSet = new HashSet<>();
        }
        propSet.add(prop);
        lazyContext.set(propSet);
    }

    /**
     * 获取排除字段
     * 
     * @return 字段集合
     */
    public static Set<String> getNotLazy() {
        return lazyContext.get() == null ? new HashSet<String>() : lazyContext.get();
    }

    /**
     * 放入线程变量 -可以直接在sql中使用
     * 
     * @param key
     *            key
     * @param value
     *            value
     */
    public static void put(String key, Object value) {
        Map<String, Object> map = sqlParams.get();
        if (map == null) {
            map = new HashMap<>();
        }
        map.put(key, value);
        sqlParams.set(map);
    }

    /**
     * 设置线程变量 -可以直接在sql中使用
     * 
     * @param sqlParams
     *            包装参数
     */
    public static void setSqlParams(Map<String, Object> sqlParams) {
        ContextBeanHolder.sqlParams.set(sqlParams);
    }

    /**
     * 获取线程中的sql参数
     * 
     * @return 参数
     */
    public static Map<String, Object> getSqlParams() {
        Map<String, Object> map = sqlParams.get();
        if (map == null) {
            map = new HashMap<>();
        }
        return map;
    }

    /**
     * 清空 -lazyContext
     */
    public static void clear() {
        lazyContext.remove();
    }

    /**
     * 清空 -sqlParams
     */
    public static void clearSqlParams() {
        sqlParams.remove();
    }
}
 public class JkException extends RuntimeException {

	private static final long serialVersionUID = 7430449458407101783L;

	public JkException(String message){
		super(message);
	}
	
	public JkException(Throwable cause)
	{
		super(cause);
	}
	
	public JkException(String message,Throwable cause)
	{
		super(message,cause);
	}
} public class Page<T> implements java.io.Serializable {
    private static final long serialVersionUID = -3011180843826014135L;
    @Key
    private Integer page = 1;// 当前页
    private Long total = 0l;// 总数
    private Integer size = 10;// 每页数量
    private List<T> rows = new ArrayList<>();
    private String order;// 排序
    private List<SearchFilter> searchFilter = new ArrayList<>();// 检索条件

    /**
     * 总数
     * 
     * @return 总数
     */
    public Long getTotal() {
        return total;
    }

    /**
     * 总数
     * 
     * @param total
     *            总数
     */
    public void setTotal(Long total) {
        this.total = total;
    }

    /**
     * 当前页
     * 
     * @return 当前页
     */
    public Integer getPage() {
        return page;
    }

    /**
     * 当前页
     * 
     * @param page
     *            页数
     */
    public void setPage(Integer page) {
        if (page == null || page <= 0) {
            page = 1;
        }
        this.page = page;
    }

    /**
     * 每页数量
     * 
     * @return 每页数量
     */
    public Integer getSize() {
        if (size == null) {
            size = 10;
        }
        return size;
    }

    /**
     * 每页数量
     * 
     * @param size
     *            每页数量
     */
    public void setSize(Integer size) {
        if (size != null) {
            this.size = size;
        }
    }

    /**
     * 结果集
     * 
     * @return 结果集合
     */
    public List<T> getRows() {
        if (rows == null) {
            setRows(new ArrayList<T>());
        }
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }

    /**
     * 排序
     * 
     * @return 排序
     */
    public String getOrder() {
        return order;
    }

    /**
     * 排序
     * 
     * @param order
     *            排序
     */
    public void setOrder(String order) {
        this.order = order;
    }

    /**
     * 检索条件
     * 
     * @return 获取检索条件
     */
    public List<SearchFilter> getSearchFilter() {
        return searchFilter;
    }

    /**
     * 检索条件
     * 
     * @param searchFilter
     *            设置检索条件
     */
    public void setSearchFilter(List<SearchFilter> searchFilter) {
        this.searchFilter = searchFilter;
    }

    /**
     * 添加检索条件
     * 
     * @param searchFilter
     *            条件
     */
    public void addFilter(SearchFilter searchFilter) {
        getSearchFilter().add(searchFilter);
    }
}
 public class RunConfing {
    private static ThreadLocal<RunConfing> config = new ThreadLocal<RunConfing>();
    /** 数据库类型 */
    private transient String dbType;
    /** 数据源 */
    private transient DataSource dataSource;
    /** 懒加载 */
    private transient Boolean lazybean;
    /** sql 模板路径 */
    private transient String sqlPath;
    private transient String dataSourceId;
    private transient String mappingPath;

    public String getDbType() {
        return dbType;
    }

    public RunConfing setDbType(String dbType) {
        this.dbType = dbType;
        return this;
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public RunConfing setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        return this;
    }

    public Boolean isLazybean() {
        return lazybean;
    }

    public RunConfing setLazybean(Boolean lazybean) {
        this.lazybean = lazybean;
        return this;
    }

    public String getSqlPath() {
        return this.sqlPath;
    }

    public RunConfing setSqlPath(String sqlpath) {
        this.sqlPath = sqlpath;
        return this;
    }

    public RunConfing setDataSourceId(String dataSourceId) {
        this.dataSourceId = dataSourceId;
        return this;
    }
    public String getDataSourceId() {
        return this.dataSourceId;
    }

    public String getMappingPath() {
        return mappingPath;
    }

    public RunConfing setMappingPath(String mappingPath) {
        this.mappingPath = mappingPath;
        return this;
    }

    public void bind() {
        bindConfing(this);
    }

    public static void clear() {
        config.remove();
    }

    public static RunConfing getConfig() {
        RunConfing runConfing = config.get();
        if (runConfing == null) {
            bindConfing(new RunConfing());
        }
        return config.get();
    }

    public static void bindConfing(RunConfing config) {
        RunConfing.config.set(config);
    }

    public Connection getConnection() {
        if (dataSource == null) {
            throw new RuntimeException("dataSource is null  no bean dataSource please set spring xml ");
        }
        try {
            return DataSourceUtils.getConnection(dataSource);
        } catch (CannotGetJdbcConnectionException e) {
            try {
                return dataSource.getConnection();
            } catch (SQLException e1) {
                throw new JkException(e);
            }
        }
    }

    public void doReleaseConnection(Connection con) {
        try {
            if (dataSource != null) {
                DataSourceUtils.doReleaseConnection(con, dataSource);
            } else {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
 public class BeanListHandle<T> implements ResultHandle<List<T>> {
    private static final Log logger = LogFactory.getLog(BeanListHandle.class);
    private Class<T> clazz;
    private int _depth;
    private int _maxDepth;

    public BeanListHandle(Class<T> clazz, int depth, int maxDepth) {
        this.clazz = clazz;
        this._depth = depth;
        this._maxDepth = maxDepth;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<T> handle(ResultSet rs) {
        if (_depth > _maxDepth) {
            logger.debug("Bean load is max Depth ");
            return new ArrayList<>();
        }
        RunConfing config = RunConfing.getConfig();
        // 返回map对象
        ResultHandle<List<Map<String, Object>>> handle = new MapListHandle();
        List<Map<String, Object>> outMap = handle.handle(rs);
        if (clazz.isAssignableFrom(Map.class)) {
            return (List<T>) outMap;
        }
        List<T> resultlist = new ArrayList<T>();
        final Map<String, String> filedMap = SqlUtils.getEntityColumnFiledMap(clazz);
        // 处理map 包装实体
        for (Map<String, Object> map : outMap) {
            try {
                T o = null;
                if (!JkBeanUtils.isBeanClass(clazz)) {
                    Object val = map.values().iterator().next();
                    if(val!=null){
                        o = clazz.getConstructor(String.class).newInstance(String.valueOf(val));
                    }
                    resultlist.add(o);
                    continue;
                }
                // 懒加载开启
                if (config.isLazybean()) {
                    org.springframework.cglib.proxy.Enhancer enhancer = new org.springframework.cglib.proxy.Enhancer();
                    enhancer.setSuperclass(clazz);
                    enhancer.setCallback(new LazyBeanProxy(config, _depth, _maxDepth));
                    o = (T) enhancer.create();
                } else {
                    o = clazz.newInstance();
                }
                o = (T) JkBeanUtils.mapToObject(map, o, new PsKey() {
                    public String before(String key) {
                        String pname = filedMap.get(key);
                        if (pname != null) {
                            key = pname;
                        }
                        // 转换对象属性名字
                        key = JkBeanUtils.columnToHump(key);
                        return key;
                    }
                });
                resultlist.add(o);
                // 非懒加载
                if (!config.isLazybean()) {
                    // 对象包含sql
                    Map<String, String> columnSqlMp = SqlUtils.getColumnSqlMp(clazz);
                    if (!columnSqlMp.isEmpty()) {
                        int now_depth = new Integer(_depth) + 1;
                        DataMapper mapper = DataMapper.getMapper();
                        for (Entry<String, String> entry : columnSqlMp.entrySet()) {
                            String name = entry.getKey();
                            String sql = entry.getValue();
                            // JkBeanUtils.columnToHump(k)
                            List<Object> params = new ArrayList<>();
                            // 组装sql+参数
                            sql = mapper.placeholderSqlParam(sql, params, o);
                            Field field = JkBeanUtils.getObjField(clazz, name);
                            Class<?> type = field.getType();
                            ResultType result = SqlUtils.getAnnotation(field,ResultType.class);
                            if (result != null) {
                                type = result.value();
                            }
                            List<?> oval = mapper.query(sql, new BeanListHandle<>(type, now_depth, _maxDepth), params);
                            JkBeanUtils.setProperty(o, name, oval);
                        }
                    }
                    
                }
            } catch (Exception e) {
                logger.error(e);
            }
        }
        return resultlist;
    }
} public class JdbcTypesUtils {
    /* jdbc type > java.sql.Types */
    private static Map<String, Integer> jdbcTypes = new HashMap<>();
    /* javatype > jdbc type */
    private static Map<Class<?>, String> javaToJdbcTypesMp = new HashMap<>();
    /* java.sql.Types > javatype */
    private static Map<Integer, Class<?>> jdbcToJavaTypesMp = new HashMap<>();
    static {
        Field[] fields = java.sql.Types.class.getFields();
        for (int i = 0, len = fields.length; i < len; ++i) {
            if (Modifier.isStatic(fields[i].getModifiers())) {
                try {
                    String name = fields[i].getName();
                    Integer value = (Integer) fields[i].get(java.sql.Types.class);
                    jdbcTypes.put(name, value);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        javaToJdbcTypesMp.put(Integer.class, "INTEGER");
        javaToJdbcTypesMp.put(Long.class, "BIGINT");
        javaToJdbcTypesMp.put(Boolean.class, "TINYINT");
        javaToJdbcTypesMp.put(Date.class, "DATE");
        javaToJdbcTypesMp.put(String.class, "VARCHAR");
        javaToJdbcTypesMp.put(BigDecimal.class, "DECIMAL");
        javaToJdbcTypesMp.put(Double.class, "DOUBLE");
        javaToJdbcTypesMp.put(Float.class, "FLOAT");
        javaToJdbcTypesMp.put(null, "NULL");
        javaToJdbcTypesMp.put(Blob.class, "BLOB");
        javaToJdbcTypesMp.put(Clob.class, "CLOB");
        // 初始化jdbcToJavaTypesMp：
        jdbcToJavaTypesMp.put(new Integer(Types.LONGNVARCHAR), String.class); // -16 字符串
        jdbcToJavaTypesMp.put(new Integer(Types.NCHAR), String.class); // -15 字符串
        jdbcToJavaTypesMp.put(new Integer(Types.NVARCHAR), String.class); // -9 字符串
        jdbcToJavaTypesMp.put(new Integer(Types.ROWID), String.class); // -8 字符串
        jdbcToJavaTypesMp.put(new Integer(Types.BIT), Boolean.class); // -7 布尔
        jdbcToJavaTypesMp.put(new Integer(Types.TINYINT), Byte.class); // -6 数字
        jdbcToJavaTypesMp.put(new Integer(Types.BIGINT), Long.class); // -5 数字
        jdbcToJavaTypesMp.put(new Integer(Types.LONGVARBINARY), Blob.class); // -4 二进制
        jdbcToJavaTypesMp.put(new Integer(Types.VARBINARY), Blob.class); // -3 二进制
        jdbcToJavaTypesMp.put(new Integer(Types.BINARY), Blob.class); // -2 二进制
        jdbcToJavaTypesMp.put(new Integer(Types.LONGVARCHAR), String.class); // -1 字符串
        jdbcToJavaTypesMp.put(new Integer(Types.NULL), String.class); // 0 /
        jdbcToJavaTypesMp.put(new Integer(Types.CHAR), String.class); // 1 字符串
        jdbcToJavaTypesMp.put(new Integer(Types.NUMERIC), BigDecimal.class); // 2 数字
        jdbcToJavaTypesMp.put(new Integer(Types.DECIMAL), BigDecimal.class); // 3 数字
        jdbcToJavaTypesMp.put(new Integer(Types.INTEGER), Integer.class); // 4 数字
        jdbcToJavaTypesMp.put(new Integer(Types.SMALLINT), Short.class); // 5 数字
        jdbcToJavaTypesMp.put(new Integer(Types.FLOAT), BigDecimal.class); // 6 数字
        jdbcToJavaTypesMp.put(new Integer(Types.REAL), BigDecimal.class); // 7 数字
        jdbcToJavaTypesMp.put(new Integer(Types.DOUBLE), BigDecimal.class); // 8 数字
        jdbcToJavaTypesMp.put(new Integer(Types.VARCHAR), String.class); // 12 字符串
        jdbcToJavaTypesMp.put(new Integer(Types.BOOLEAN), Boolean.class); // 16 布尔
        jdbcToJavaTypesMp.put(new Integer(Types.DATALINK), String.class); // 70 /
        jdbcToJavaTypesMp.put(new Integer(Types.DATE), Date.class); // 91 日期
        jdbcToJavaTypesMp.put(new Integer(Types.TIME), Date.class); // 92 日期
        jdbcToJavaTypesMp.put(new Integer(Types.TIMESTAMP), Date.class); // 93 日期
        jdbcToJavaTypesMp.put(new Integer(Types.OTHER), Object.class); // 1111 其他类型？
        jdbcToJavaTypesMp.put(new Integer(Types.JAVA_OBJECT), Object.class); // 2000
        jdbcToJavaTypesMp.put(new Integer(Types.DISTINCT), String.class); // 2001
        jdbcToJavaTypesMp.put(new Integer(Types.STRUCT), String.class); // 2002
        jdbcToJavaTypesMp.put(new Integer(Types.ARRAY), String.class); // 2003
        jdbcToJavaTypesMp.put(new Integer(Types.BLOB), Blob.class); // 2004 二进制
        jdbcToJavaTypesMp.put(new Integer(Types.CLOB), Clob.class); // 2005 大文本
        jdbcToJavaTypesMp.put(new Integer(Types.REF), String.class); // 2006
        jdbcToJavaTypesMp.put(new Integer(Types.SQLXML), String.class); // 2009
        jdbcToJavaTypesMp.put(new Integer(Types.NCLOB), Clob.class); // 2011 大文本
    }

    /**
     * javatype - java.sql.Types
     * 
     * @param obj
     *            key
     * @return Jdbc int type
     */
    public static int getJdbcType(Object obj) {
        if (obj == null) {
            return jdbcTypes.get(javaToJdbcTypesMp.get(obj));
        }
        for (Class<?> k : javaToJdbcTypesMp.keySet()) {
            if (k != null && k.isInstance(obj)) {
                return jdbcTypes.get(javaToJdbcTypesMp.get(k));
            }
        }
        throw new RuntimeException("javaToJdbcTypesMp " + obj.getClass() + " not match jdbcTypes");
    };

    /**
     * 获取java对象
     * 
     * @param obj
     *            集合
     * @return string java类型
     */
    public static String getJdbcType(Collection<?> obj) {
        if (obj == null || obj.isEmpty()) {
            return javaToJdbcTypesMp.get(obj);
        }
        Object next = obj.iterator().next();
        for (Class<?> k : javaToJdbcTypesMp.keySet()) {
            if (k != null && k.isInstance(next)) {
                return javaToJdbcTypesMp.get(k);
            }
        }
        throw new RuntimeException("javaToJdbcTypesMp " + obj.getClass() + " not match jdbcTypes");
    };

    /**
     * java.sql.Types - javatype
     * 
     * @param key
     *            index
     * @return java类型
     */
    public static Class<?> getJavaType(int key) {
        if (jdbcToJavaTypesMp.containsKey(key)) {
            return jdbcToJavaTypesMp.get(key);
        }
        throw new RuntimeException("jdbcToJavaTypes   not match javaTypes");
    };
} public class MapListHandle implements ResultHandle<List<Map<String, Object>>> {
    private final static String RWN = "rownum_";

    @Override
    public List<Map<String, Object>> handle(ResultSet rs) {
        List<Map<String, Object>> result = new ArrayList<>();
        try {
            ResultSetMetaData rsm = rs.getMetaData();
            int n = rsm.getColumnCount();
            List<String> names = new ArrayList<>();
            for (int i = 1; i <= n; i++) {
                // sql 查询的字段
                String name = rsm.getColumnLabel(i);
                if (RWN.equals(name)) {
                    continue;
                }
                names.add(name);
            }
            while (rs.next()) {
                Map<String, Object> mp = new HashMap<>();
                for (int index = 1; index <= names.size(); index++) {
                    String name = names.get(index - 1);
                    Object value = JdbcUtils.getResultSetValue(rs, index);
                    mp.put(name, value);
                }
                result.add(mp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
} public class NumberHandle<T> implements ResultHandle<Long> {
    @Override
    public Long handle(ResultSet rs) {
        try {
            while (rs.next()) {
                return rs.getLong(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.closeResultSet(rs);
        }
        return 0L;
    }
} public interface ResultHandle<T> {
    /**
     * 处理结果集
     * 
     * @param rs
     *            ResultSet
     * @return 结果
     */
    T handle(ResultSet rs);
} public class ExceptionUtils {
    public static RuntimeException runtimeException(Throwable e) {
        Exception ex = getException(e);
        if (ex != null&&ex instanceof RuntimeException) {
            return (RuntimeException) ex;
        }
        return new RuntimeException(ex);
    }

    public static Exception getException(Throwable e) {
        if (e == null) {
            return null;
        }
        if (e instanceof InvocationTargetException) {
            e = ((InvocationTargetException) e).getTargetException();
        }
        if (e instanceof JkException) {
            return (Exception) e;
        }
        if (e instanceof RuntimeException) {
            return new JkException(e);
        }
        Throwable cause = e.getCause();
        while (cause != null&&!(cause instanceof RuntimeException)) {
            e = cause;
            cause = cause.getCause();
        }
        return (Exception) e;
    }
}
 public class FKParse {
    private static final Log logger = LogFactory.getLog(FKParse.class);
    // 默认日期格式
    private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
    private static final String ENCODE = "utf-8";
    /**
     * 文件缓存
     */
    private static final Configuration _tplConfig = new Configuration(Configuration.VERSION_2_3_23);
    /**
     * SQL 缓存
     */
    private static final Configuration _sqlConfig = new Configuration(Configuration.VERSION_2_3_23);
    private static StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
    // 使用内嵌的(?ms)打开单行和多行模式
    private final static Pattern p = Pattern.compile("(?ms)/\\*.*?\\*/|^\\s*//.*?$");
    static {
        ObjectWrapper ow = new ObjectWrapper(Configuration.VERSION_2_3_23);
        _tplConfig.setClassForTemplateLoading(FKParse.class, "/");
        _tplConfig.setLocale(Locale.CHINESE);
        _tplConfig.setLocalizedLookup(false);
        _tplConfig.setNumberFormat("#");
        _tplConfig.setClassicCompatible(true);
        _tplConfig.setDateFormat(dateFormat);
        _tplConfig.setDateTimeFormat(dateFormat);
        _tplConfig.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX);
        _tplConfig.setObjectWrapper(ow);
        // --
        _sqlConfig.setTemplateLoader(stringTemplateLoader);
        _sqlConfig.setNumberFormat("#");
        _sqlConfig.setLocalizedLookup(false);
        _sqlConfig.setLocale(Locale.CHINESE);
        _sqlConfig.setClassicCompatible(true);
        _sqlConfig.setDateFormat(dateFormat);
        _sqlConfig.setDateTimeFormat(dateFormat);
        _sqlConfig.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX);
        _sqlConfig.setObjectWrapper(ow);
    }

    /**
     * 判断模板是否存在
     * 
     * @param tplName
     *            模板
     * @return true/false
     */
    public static boolean isExistTemplate(String tplName) {
        try {
            Template mytpl = _tplConfig.getTemplate(tplName, "UTF-8");
            if (mytpl == null) {
                return false;
            }
        } catch (Exception e) {
            throw new JkException(e);
        }
        return true;
    }

    /**
     * 解析模板
     *
     * @param tplName
     *            模板名
     * @param paras
     *            参数
     * @return 结果字符串
     */
    public static String parseTemplate(String tplName, Map<String, Object> paras) {
        try {
            StringWriter swriter = new StringWriter();
            Template mytpl = _tplConfig.getTemplate(tplName, ENCODE);
            mytpl.process(paras, swriter);
            return getSqlText(swriter.toString());
        } catch (Exception e) {
            logger.error("模板 " + tplName, e);
            throw new RuntimeException("解析SQL模板异常", e);
        }
    }

    /**
     * 获取模板原始字符串
     *
     * @param tplName
     *            模板名
     * @return 结果字符串
     */
    public static String getTemplateaString(String tplName) {
        try {
            Template mytpl = _tplConfig.getTemplate(tplName, ENCODE);
            return mytpl.toString();
        } catch (Exception e) {
            throw new RuntimeException("模板 " + tplName, e);
        }
    }

    /**
     * 解析模板
     *
     * @param tplContent
     *            模板内容
     * @param paras
     *            参数
     * @return String 模板解析后内容
     */
    public static String parseTemplateContent(String tplContent, Map<String, Object> paras) {
        try {
            StringWriter swriter = new StringWriter();
            String key = "sql_" + tplContent.hashCode();
            if (stringTemplateLoader.findTemplateSource(key) == null) {
                stringTemplateLoader.putTemplate(key, tplContent);
            }
            Template mytpl = _sqlConfig.getTemplate(key, ENCODE);
            mytpl.process(paras, swriter);
            return getSqlText(swriter.toString());
        } catch (Exception e) {
            logger.error("模板key:" + tplContent, e);
            throw new RuntimeException("解析SQL模板异常", e);
        }
    }

    /**
     * 除去无效字段，去掉注释 不然批量处理可能报错 去除无效的等于
     * 
     * @param sql
     *            字符串
     * @return 处理后的字符串
     */
    private static String getSqlText(String sql) {
        sql = p.matcher(sql).replaceAll("");
        return sql;
    }

    /***
     * 拿到静态Class的Model
     * 
     * @param config
     *            Configuration
     * @param className
     *            className
     * @return TemplateModel
     */
    public static TemplateModel useClass(Configuration config, String className) {
        BeansWrapper wrapper = (BeansWrapper) config.getObjectWrapper();
        TemplateHashModel staticModels = wrapper.getStaticModels();
        try {
            return staticModels.get(className);
        } catch (TemplateModelException e) {
            e.printStackTrace();
        }
        throw new RuntimeException(className);
    }
}
 public class JkBeanUtils {
    private final static Log logger = LogFactory.getLog(JkBeanUtils.class);
    private final static String EMPTY = "";
    private final static String SPLIT = "_";
    private final static String POINT = ".";
    private final static Pattern numberPattern = Pattern.compile("^[-\\+]?[\\d]+$");
    // 类方字段缓存
    private static Map<String, Field> classFiledCacheMp = new CacheMap<>();
    // 类方字段缓存
    private static Map<String, PropertyDescriptor> propertyDescriptorCache = new CacheMap<>();

    /**
     * 获得对象的属性类型
     * 
     * @param o
     *            对象
     * @param property
     *            属性
     * @return 属性类型
     */
    public static Class<?> getPropertyType(Object o, String property) {
        Class<?> clas = o.getClass();
        Field field = getObjField(clas, property);
        return field.getType();
    }

    /**
     * 获取属性值
     * 
     * @param o
     *            对象
     * @param property
     *            属性
     * @return 属性值
     */
    public static Object getPropertyValue(Object o, String property) {
        try {
            Field field = getObjField(o.getClass(), property);
            return field.get(o);
        } catch (Exception e) {
            throw new JkException(e);
        }
    }

    /**
     * 获取 PropertyDescriptor
     * 
     * @param o
     *            对象
     * @param property
     *            属性
     * @return PropertyDescriptor
     */
    public static PropertyDescriptor getPropertyDescriptor(Object o, String property) {
        try {
            Class<?> clazz = o.getClass();
            String key = clazz.getName().concat(POINT + property);
            PropertyDescriptor propertyDescriptor = propertyDescriptorCache.get(key);
            // 如果不存在
            if (propertyDescriptor == null) {
                initPropertyDescriptorCache(clazz);
                propertyDescriptor = propertyDescriptorCache.get(key);
            }
            if (propertyDescriptor == null) {
                throw new JkException(key + " not fond");
            }
            return propertyDescriptor;
        } catch (IntrospectionException e) {
            throw new JkException(e);
        }
    }

    // 初始化 PropertyDescriptorCache
    private static void initPropertyDescriptorCache(Class<?> clazz) throws IntrospectionException {
        String cname = clazz.getName().concat(POINT);
        BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor pd : pds) {
            String name = pd.getName();
            propertyDescriptorCache.put(cname + name, pd);
        }
    }

    /**
     * 设置参数值
     * 
     * @param o
     *            对象
     * @param property
     *            属性
     * @param value
     *            值
     * @return 对象
     */
    public static Object setProperty(Object o, String property, Object value) {
        try {
            Field field = getObjField(o.getClass(), property);
            Class<?> type = field.getType();
            if (type.isInstance(value)) {
                field.set(o, value);
            } else if (type.isAssignableFrom(Blob.class)) {
                if (value instanceof byte[]) {
                    field.set(o, new BlobImpl((byte[]) value));
                    return o;
                }
                if (value instanceof Clob) {
                    field.set(o, new BlobImpl(LobUtils.toBytes((Clob) value)));
                    return o;
                }
            } else if (type.isAssignableFrom(String.class)) {
                if (value instanceof List) {
                    List<?> lv = (List<?>) value;
                    if (lv == null || lv.size() == 0) {
                        return o;
                    }
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < lv.size(); i++) {
                        if (i > 0) {
                            sb.append(",");
                        }
                        sb.append(lv.get(i));
                    }
                    field.set(o, sb.toString());
                    return o;
                } else if (value instanceof Clob) {
                    String vl = LobUtils.toStr((Clob) value);
                    field.set(o, vl);
                    return o;
                } else if (value instanceof Blob) {
                    String vl = LobUtils.toStr((Blob) value);
                    field.set(o, vl);
                    return o;
                } else {
                    if (value != null) {
                        field.set(o, value.toString());
                    }
                    return o;
                }
            } else if (type.isAssignableFrom(Boolean.class)) {
                if (value instanceof Boolean) {
                    field.set(o, value);
                } else if (value instanceof Number) {
                    String v = value.toString();
                    field.set(o, (v.equals("1") || v.equalsIgnoreCase("y")) ? true : false);
                }
            } else if (type.isEnum()) {// 枚举2016.07.13 tao add
                try {
                    Enum<?>[] ts = (Enum[]) type.getEnumConstants();
                    for (Enum<?> ob : ts) {
                        if (ob.name().equals(value.toString())) {
                            field.set(o, ob);
                            return o;
                        }
                    }
                } catch (Exception e) {
                    logger.warn(e);
                }
            } else {
                if (value instanceof List) {
                    List<?> lv = (List<?>) value;
                    if (lv == null || lv.size() == 0) {
                        return o;
                    }
                    if (lv.size() == 1) {
                        field.set(o, lv.get(0));
                    } else {
                        throw new JkException(" list:size = " + lv.size());
                    }
                } else if (value instanceof Boolean) {
                    if (type.isAssignableFrom(Integer.class) || type.isAssignableFrom(Short.class) || type.isAssignableFrom(Long.class)
                            || type.isAssignableFrom(Number.class)) {
                        field.set(o, (Boolean) value ? 1 : 0);
                    }
                } else if (value instanceof Number) {
                    Number number = (Number) value;
                    if (type.isAssignableFrom(Long.class)) {
                        field.set(o, number.longValue());
                    } else if (type.isAssignableFrom(Integer.class)) {
                        field.set(o, number.intValue());
                    } else if (type.isAssignableFrom(Float.class)) {
                        field.set(o, number.floatValue());
                    } else if (type.isAssignableFrom(Double.class)) {
                        field.set(o, number.doubleValue());
                    } else if (type.isAssignableFrom(Short.class)) {
                        field.set(o, number.shortValue());
                    } else {
                        try {
                            field.set(o, type.getConstructor(String.class).newInstance(value.toString()));
                        } catch (InstantiationException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                            logger.warn(e);
                        }
                    }
                } else {
                    field.set(o, value);
                }
            }
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
        return o;
    }

    /**
     * 获得Field 包含父类
     * 
     * @param clazz
     *            class
     * @param name
     *            名字
     * @return Field
     */
    public static Field getObjField(Class<?> clazz, String name) {
        return getObjField(clazz, name, 1);
    }

    /**
     * 获得Field 包含父类
     * 
     * @param clazz
     *            class
     * @param name
     *            名字
     * @param n
     *            层数
     * @return Field
     */
    private static Field getObjField(Class<?> clazz, String name, int n) {
        String key = clazz.getName().concat(POINT + name);
        Field field = classFiledCacheMp.get(key);
        if (field != null) {
            return field;
        }
        if (n > 2) {
            throw new JkException(key + " not found");
        }
        initFileCache(clazz);
        return getObjField(clazz, name, ++n);
    }

    /**
     * 初始化加载 clazz-field
     * 
     * @param clazz
     *            class
     */
    private static void initFileCache(Class<?> clazz) {
        List<Field> allFields = getAllFields(clazz);
        for (Field field : allFields) {
            String namne = field.getName();
            String key = clazz.getName().concat(POINT + namne);
            classFiledCacheMp.put(key, field);
        }
    }

    /**
     * 获得所有 Field 包含父类
     * 
     * @param clazz
     *            class
     * @return field 集合
     */
    public static List<Field> getAllFields(Class<?> clazz) {
        List<Field> allField = new ArrayList<>();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            allField.add(field);
        }
        Class<?> superclass = clazz.getSuperclass();
        if (superclass != null) {
            if (superclass.getDeclaredFields().length > 0) {
                allField.addAll(getAllFields(superclass));
            }
        }
        return allField;
    }

    /**
     * 首字母大写 <br>
     * user - User
     * 
     * @param column
     *            字符
     * @return 结果
     */
    public static String firstToHump(String column) {
        if (isBlank(column)) {
            return EMPTY;
        } else {
            return column.substring(0, 1).toUpperCase() + column.substring(1);
        }
    }

    /**
     * 首字母小写
     * 
     * @param column
     *            字符
     * @return 结果
     */
    public static String firstToMix(String column) {
        if (isBlank(column)) {
            return EMPTY;
        } else {
            return column.substring(0, 1).toLowerCase() + column.substring(1);
        }
    }

    /**
     * 字段转驼峰命名 <br>
     * user_name - userName
     * 
     * @param column
     *            字符
     * @return 结果
     */
    public static String columnToHump(String column) {
        if (isBlank(column)) {
            return EMPTY;
        } else if (column.indexOf(SPLIT) < 0) {
            return column.substring(0, 1).toLowerCase() + column.substring(1);
        } else {
            StringBuilder result = new StringBuilder();
            String[] columns = column.split(SPLIT);
            for (String columnSplit : columns) {
                if (columnSplit.isEmpty()) {
                    continue;
                }
                if (result.length() == 0) {
                    result.append(columnSplit.toLowerCase());
                } else {
                    result.append(columnSplit.substring(0, 1).toUpperCase()).append(columnSplit.substring(1).toLowerCase());
                }
            }
            return result.toString();
        }
    }

    /**
     * map 返回 实体
     * 
     * @param map
     *            map
     * @param classz
     *            class or object
     * @return 对象
     */
    public static Object mapToObject(Map<String, Object> map, Object classz) {
        return mapToObject(map, classz, null);
    }

    /**
     * map 返回 实体
     * 
     * @param map
     *            map
     * @param classz
     *            class
     * @param psKey
     *            key助理
     * @return 对象
     */
    public static Object mapToObject(Map<String, Object> map, Object classz, PsKey psKey) {
        Object obj = classz;
        if (classz instanceof Class) {
            try {
                obj = ((Class<?>) classz).newInstance();
            } catch (Exception e) {
                throw new JkException(e);
            }
        }
        for (Entry<String, Object> entry : map.entrySet()) {
            try {
                String key = entry.getKey();
                if (psKey != null) {
                    key = psKey.before(key);
                }
                Object value = entry.getValue();
                setProperty(obj, key, value);
            } catch (Exception e) {
                logger.warn(e);
            }
        }
        return obj;
    }

    public interface PsKey {
        String before(String key);
    };

    /**
     * map 返回 实体
     * 
     * @param <T>
     *            泛型
     * @param map
     *            map
     * @param classz
     *            class
     * @return 对象
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> classz) {
        return (T) mapToObject(map, classz);
    }

    /**
     * 字段转驼峰命名 <br>
     * userName - user_name
     * 
     * @param column
     *            字符
     * @return 结果
     */
    public static String columnToHumpReversal(String column) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < column.length(); i++) {
            char charAt = column.charAt(i);
            if (Character.isUpperCase(charAt)) {
                result.append("_");
                charAt = Character.toLowerCase(charAt);
            }
            result.append(charAt);
        }
        return result.toString();
    }

    /**
     * 判断段是否是数字
     * 
     * @param str
     *            字符
     * @return true/false
     */
    public static boolean isNumber(String str) {
        return numberPattern.matcher(str).matches();
    }

    /**
     * 是否是实体
     * 
     * @param clz
     *            class
     * @return true/false
     */
    public static boolean isBeanClass(Class<?> clz) {
        try {
            String s = clz.getName();
            if (s.indexOf("java.lang") > -1) {
                return false;
            }
            if (s.indexOf("java.util") > -1) {
                return false;
            }
            if (s.indexOf("java.math") > -1) {
                return false;
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 判断的包装类
     * 
     * @param clz
     *            class
     * @return true/false
     */
    public static boolean isWrapClass(Class<?> clz) {
        try {
            return ((Class<?>) clz.getField("TYPE").get(null)).isPrimitive();
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断的是否为空
     * 
     * @param s
     *            字符串
     * @return 是否为空
     */
    public static boolean isBlank(String s) {
        if (s == null || EMPTY.equals(s.trim())) {
            return true;
        }
        return false;
    }

    /**
     * 返回 maxDepth default 2
     * 
     * @param classType
     *            class
     * @return 最大深度
     */
    public static int getMaxDepth(Class<?> classType) {
        int maxDepth = 2;
        if (classType != null) {
            Depth depth = classType.getAnnotation(Depth.class);
            if (depth != null) {
                maxDepth = depth.value();
            } else {
                Map<String, String> configMapping = MappingProperty.getConfigMapping();
                String key = classType.getName() + "[depth]";
                String val = configMapping.get(key);
                if (val != null) {
                    maxDepth = Integer.valueOf(val);
                }
            }
        }
        return maxDepth;
    }
}
 public class SqlUtils {
    private static Map<Object, Object> mapCache = new CacheMap<>();
    private static Map<String, List<String>> entityAttrMp = new CacheMap<>();
    private static Map<String, List<String>> entityColumnMp = new CacheMap<>();
    private static Map<String, Map<String, String>> columnSqlMp = new CacheMap<>();
    private static Map<String, Boolean> sqlforce = new CacheMap<>();

    public enum TYPE {
        INSERT, SELECT, UPDATE
    };

    /**
     * 获取sql
     * 
     * @param clazz
     *            class
     * @param type
     *            枚举TYPE
     * @return sql
     */
    public static String getSqls(Class<?> clazz, TYPE type) {
        try {
            String sql = null;
            if (TYPE.SELECT.equals(type)) {
                sql = getSelectSqls(clazz);
            }
            if (TYPE.INSERT.equals(type)) {
                sql = getInsertSqls(clazz);
            }
            if (TYPE.UPDATE.equals(type)) {
                sql = getUpdateSqls(clazz);
            }
            return sql;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询sql
     * 
     * @param clazz
     *            class
     * @return sql
     */
    public static String getSelectSqls(Class<?> clazz) {
        String key = clazz.getName();
        String keyCache = key + ".select";
        if (mapCache.containsKey(keyCache)) {
            return (String) mapCache.get(keyCache);
        }
        String table = getTableName(clazz);
        if (!entityColumnMp.containsKey(key)) {
            initData(clazz);
        }
        StringBuilder sb = new StringBuilder("select ");
        List<String> atts = entityColumnMp.get(key);
        Map<String, String> filedMap = getEntityColumnFiledMap(clazz);
        for (int i = 0; i < atts.size(); i++) {
            String col = atts.get(i);
            String prop = filedMap.get(col);
            if (i > 0) {
                sb.append(",");
            }
            sb.append(getCol(col));
            if (!col.equals(prop)) {
                sb.append(" as " + prop);
            }
        }
        sb.append(" from " + table + " _tb");
        String out = sb.toString();
        mapCache.put(keyCache, out);
        return out;
    }

    /**
     * 插入sql
     * 
     * @param clazz
     *            class
     * @return sql
     */
    public static String getInsertSqls(Class<?> clazz) {
        String key = clazz.getName();
        String keyCache = key + ".insert";
        if (mapCache.containsKey(keyCache)) {
            return (String) mapCache.get(keyCache);
        }
        String table = getTableName(clazz);
        if (!entityColumnMp.containsKey(key)) {
            initData(clazz);
        }
        StringBuilder sb = new StringBuilder("insert into ");
        sb.append(table);
        sb.append("(");
        List<String> clos = entityColumnMp.get(key);
        for (int i = 0; i < clos.size(); i++) {
            String col = clos.get(i);
            col = getCol(col);
            if (i == 0) {
                sb.append(col);
            } else {
                sb.append("," + col);
            }
        }
        sb.append(")values(");
        for (int i = 0; i < clos.size(); i++) {
            if (i == 0) {
                sb.append(" ? ");
            } else {
                sb.append(", ? ");
            }
        }
        sb.append(")");
        String out = sb.toString();
        mapCache.put(keyCache, out);
        return out;
    }

    /**
     * 更新sql
     * 
     * @param clazz
     *            class
     * @return sql
     */
    public static String getUpdateSqls(Class<?> clazz) {
        String key = clazz.getName();
        String keyCache = key + ".update";
        if (mapCache.containsKey(keyCache)) {
            return (String) mapCache.get(keyCache);
        }
        String table = getTableName(clazz);
        if (!entityColumnMp.containsKey(key)) {
            initData(clazz);
        }
        StringBuilder sb = new StringBuilder("update ");
        sb.append(table);
        sb.append(" set ");
        List<String> clos = entityColumnMp.get(key);
        for (int i = 0; i < clos.size(); i++) {
            String col = clos.get(i);
            col = getCol(col);
            if (i == 0) {
                sb.append(col + " = ? ");
            } else {
                sb.append("," + col + " =? ");
            }
        }
        String out = sb.toString();
        mapCache.put(keyCache, out);
        return out;
    }

    /**
     * 初始化
     * 
     * @param clazz
     *            class
     */
    private static void initData(Class<?> clazz) {
        String k = clazz.getName();
        List<String> attrs = new ArrayList<>();
        List<String> columns = new ArrayList<>();
        Map<String, String> cmsql = new LinkedCaseInsensitiveMap<>();
        List<Field> listField = JkBeanUtils.getAllFields(clazz);
        for (Field field : listField) {
            // 排除静态
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            String fieldName = field.getName();
            if (fieldName.contains("CGLIB")) {
                continue;
            }
            Transient tr = getAnnotation(field,Transient.class);
            if (tr != null) {
                continue;
            }
            Column column = getAnnotation(field,Column.class);
            String columnString = JkBeanUtils.columnToHumpReversal(fieldName);
            // 注解字段
            if (column != null) {
                columnString = column.value();
            }
            String KeyMappingColumn = k + "." + fieldName;
     
            // 注解sql
            Sql Sql = getAnnotation(field,Sql.class);
            if (Sql != null) {
                cmsql.put(fieldName, Sql.value());
                sqlforce.put(KeyMappingColumn, Sql.force());
            } else {
                attrs.add(fieldName);
                columns.add(columnString);
            }
        }
        entityAttrMp.put(k, attrs);
        entityColumnMp.put(k, columns);
        columnSqlMp.put(k, cmsql);
    }

    /**
     * 获取表名
     * 
     * @param clazz
     *            class
     * @return 表名
     */
    public static String getTableName(Class<?> clazz) {
        String k = clazz.getName() + "[Table]";
        Map<String, String> mapping = MappingProperty.getConfigMapping();
        if (mapping.containsKey(k)) {
            return mapping.get(k);
        }
        if (mapCache.containsKey(k)) {
            return (String) mapCache.get(k);
        }
        Table table = clazz.getAnnotation(Table.class);
        String result = clazz.getSimpleName();
        if (table != null) {
            result = table.value();
        }
        mapCache.put(k, result);
        return result;
    }

    /**
     * 获取序列名
     * 
     * @param clazz
     *            class
     * @return 序列名字
     */
    public static String getSequenceGeneratorVal(Class<?> clazz) {
        String k = clazz.getName() + ".sequenceGenerator";
        if (mapCache.containsKey(k)) {
            return (String) mapCache.get(k);
        }
        SequenceGenerator sg = clazz.getAnnotation(SequenceGenerator.class);
        String result = null;
        if (sg != null) {
            result = sg.value();
        }
        mapCache.put(k, result);
        return result;
    }

    /**
     * 获得主键字段<br>
     * [0] name<br>
     * [1] cloumn<br>
     * [2] type<br>
     * 
     * @param clazz
     *            class
     * @return 数组
     */
    public static Object[] getTableKey(Class<?> clazz) {
        String k = clazz.getName() + "[Key]";
        if (mapCache.containsKey(k)) {
            return (Object[]) mapCache.get(k);
        }
        String KeyMapping = MappingProperty.getConfigMapping().get(k);
        Object[] obj = new Object[3];
        List<Field> lsField = JkBeanUtils.getAllFields(clazz);
        Field delaltfield = null;
        for (Field field : lsField) {
            Key Key = getAnnotation(field,Key.class);
            Column column = getAnnotation(field,Column.class);
            String fieldName = field.getName();
            obj[0] = fieldName;
            obj[1] = fieldName;
            obj[2] = field.getType();
            if (column != null) {
                obj[1] = column.value();
            }
            if("id".equalsIgnoreCase(fieldName)){
                delaltfield = field;
            }
            if (Key != null || fieldName.equalsIgnoreCase(KeyMapping)) {
                mapCache.put(k, obj);
                return obj;
            }
        }
        if(delaltfield!=null){
            mapCache.put(k, obj);
            return obj;
        }
        return null;
    }

    /**
     * 获得实体属性
     * 
     * @param clazz
     *            class
     * @return 属性集合
     */
    public static List<String> getEntityAttrMp(Class<?> clazz) {
        String key = clazz.getName();
        List<String> list = entityAttrMp.get(key);
        if (list == null) {
            initData(clazz);
            list = entityAttrMp.get(key);
        }
        return list;
    }

    /**
     * 获得实体db字段
     * 
     * @param clazz
     *            class
     * @return db字段集合
     */
    public static List<String> getEntityColumnMp(Class<?> clazz) {
        String key = clazz.getName();
        List<String> list = entityColumnMp.get(key);
        if (list == null) {
            initData(clazz);
            list = entityColumnMp.get(key);
        }
        return list;
    }

    /**
     * 获得字段注解sql
     * 
     * @param clazz
     *            class
     * @return sql
     */
    public static Map<String, String> getColumnSqlMp(Class<?> clazz) {
        String key = clazz.getName();
        if (!columnSqlMp.containsKey(key)) {
            initData(clazz);
        }
        return columnSqlMp.get(key);
    }

    /**
     * sql强制查询
     * 
     * @param key
     *            key
     * @return ture/false
     */
    public static Boolean getSqlForce(String key) {
        Boolean force = sqlforce.get(key);
        if (force == null) {
            force = false;
        }
        return force;
    }

    /**
     * 获得属性和注解map
     * 
     * @param clazz
     *            class
     * @return key属性 value注解
     */
    public static Map<String, String> getEntityFiledColumnMap(Class<?> clazz) {
        String kname = clazz.getName();
        String k = kname + "#filedColMap#";
        if (mapCache.containsKey(k)) {
            return (Map<String, String>) mapCache.get(k);
        }
        Map<String, String> mp = new LinkedCaseInsensitiveMap<>();
        List<Field> lsField = JkBeanUtils.getAllFields(clazz);
        for (Field field : lsField) {
            // 排除静态
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            String fieldName = field.getName();
            if (fieldName.indexOf("CGLIB") > -1) {
                continue;
            }
            Sql Sql = getAnnotation(field,Sql.class);
            if (Sql != null) {
                continue;
            }
            String columnString;
            Column column = getAnnotation(field,Column.class);
            if (column != null) {
                columnString = column.value();
            } else {
                columnString = JkBeanUtils.columnToHumpReversal(field.getName());
            }
            mp.put(field.getName(), columnString);
        }
        mapCache.put(k, mp);
        return mp;
    }

    /**
     * 获得属性和注解map
     * 
     * @param clazz
     *            class
     * @return key属性 value注解
     */
    public static Map<String, String> getEntityColumnFiledMap(Class<?> clazz) {
        String k = clazz.getName() + "#colFiledMap#";
        if (mapCache.containsKey(k)) {
            return (Map<String, String>) mapCache.get(k);
        }
        Map<String, String> mp = new LinkedCaseInsensitiveMap<>();
        Map<String, String> filedCol = getEntityFiledColumnMap(clazz);
        for (String key : filedCol.keySet()) {
            mp.put(filedCol.get(key), key);
        }
        mapCache.put(k, mp);
        return mp;
    }

    /**
     * 获取搜索参数
     * 
     * @param classType
     *            calss
     * @param page
     *            Page
     * @param params
     *            结果参数
     * @return sql
     */
    public static String getSearchParames(Class<?> classType, Page<?> page, List<Object> params) {
        List<SearchFilter> filters = page.getSearchFilter();
        String query = getSearchParames(classType, filters, params);
        if (isNotBlank(page.getOrder())) {
            query = query.concat("  order by " + page.getOrder());
        }
        return query;
    }

    /**
     * 获取搜索参数
     * 
     * @param classType
     *            calss
     * @param filters
     *            参数
     * @param params
     *            结果参数
     * @return sql
     */
    public static String getSearchParames(Class<?> classType, List<SearchFilter> filters, List<Object> params) {
        StringBuilder sb = new StringBuilder();
        if (filters != null) {
            Map<String, String> filedMap = getEntityFiledColumnMap(classType);
            for (SearchFilter filter : filters) {
                Operator operator = filter.getOperator();
                String property = filter.getProperty();
                if (isNotBlank(property)) {
                    String column = filedMap.get(property);
                    if (sb.length() > 0) {
                        sb.append(" and ");
                    } else {
                        sb.append(" where ");
                    }
                    if (isNotBlank(column)) {
                        sb.append(column);
                    } else {
                        sb.append(property);
                    }
                    Object value = filter.getValue();
                    if (value == null) {
                        sb.append(" is null ");
                        continue;
                    }
                    if (operator.equals(Operator.in)) {
                        sb.append(" in(" + joinCollect(value, params) + ") ");
                    } else if (operator.equals(Operator.inSql)) {
                        sb.append(" in(" + value + ") ");
                    } else if (operator.equals(Operator.notInSql)) {
                        sb.append(" not in(" + value + ") ");
                    } else if (operator.equals(Operator.concat)) {
                        sb.append(" " + value);
                    }else if (operator.equals(Operator.not)) {
                        sb.append(" not in(" + joinCollect(value, params) + ") ");
                    } else {
                        sb.append(operator.getOp());
                        params.add(value);
                    }
                }
            }
        }
        return sb.toString();
    }

    /**
     * 判断是否为空
     * 
     * @param s
     *            字符串
     * @return 结果
     */
    private static boolean isNotBlank(String s) {
        if (s == null || "".equals(s.trim())) {
            return false;
        }
        return true;
    }

    /**
     * 获取col
     * 
     * @param col
     *            字符
     * @return col
     */
    private static String getCol(String col) {
        if (DataMapper.DATABSE_TYPE_ORACLE.equalsIgnoreCase(RunConfing.getConfig().getDbType())) {
            return "\"" + col.toUpperCase() + "\"";
        } else {
            return col;
        }
    }

    /**
     * 拼接字符串
     * 
     * @param cols
     *            参数值
     * @param params
     *            结果值
     * @return 字符串
     */
    private static String joinCollect(Object cols, List<Object> params) {
        StringBuilder sbf = new StringBuilder();
        if (cols instanceof Collection) {
            for (Object v : (Collection<?>) cols) {
                sbf.append(",?");
                params.add(v);
            }
        } else if (cols instanceof Object[]) {
            for (Object v : (Object[]) cols) {
                sbf.append(",?");
                params.add(v);
            }
        } else {
            return cols.toString();
        }
        if (sbf.length() > 0) {
            sbf.deleteCharAt(0);
        }
        return sbf.toString();
    }

    /**
     * sql参数转义
     * 
     * @param str
     *            入参
     * @return 转以后
     */
    public static String escapeSql(String str) {
       /** if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char src = str.charAt(i);
            switch (src) {
                case '\'':
                    sb.append("''");
                    break;
                case '\"':
                case '\\':
                    sb.append('\\');
                default:
                    sb.append(src);
                    break;
            }
        }
        return sb.toString();*/
        return str;
    }

    /**
     * 获得配置转换注解
     * 
     * @param field
     *            字段
     * @param classz
     *            注解
     * @param <T>
     *            注解泛型
     * @return 注解类
     */
    public static <T extends Annotation> T getAnnotation(Field field, Class<T> classz) {
        T annotation = field.getAnnotation(classz);
        if (annotation != null) {
            return annotation;
        }
        Map<String, String> mapping = MappingProperty.getConfigMapping();
        
        String objName = field.getDeclaringClass().getName();
        String fieldName = field.getName();
        String annoName = classz.getSimpleName();
        String key = objName + "." + fieldName + "[" + annoName + "]";
        String property = mapping.get(key);
        
        if (property != null) {
            try {
                Map<String, Object> map = new HashMap<>();
                map.put("value", property);
                Method[] fields = classz.getDeclaredMethods();
                for (Method method : fields) {
                    String name = method.getName();
                    Class<?> returnType = method.getReturnType();
                    if (returnType.isAssignableFrom(Class.class)) {
                        map.put("value", Class.forName(property));
                    }
                    Object value = mapping.get(key + "[" + name + "]");
                    if (!map.containsKey(name)) {
                        if (value != null) {
                            if (returnType.isAssignableFrom(boolean.class)) {
                                value = Boolean.valueOf(value.toString());
                            } else if (returnType.isAssignableFrom(Number.class) || returnType.isAssignableFrom(Boolean.class)) {
                                value = returnType.getConstructor(String.class).newInstance(value.toString());
                            }
                            map.put(name, value);
                        } else {
                            map.put(name, method.getDefaultValue());
                        }
                    }
                }
                return (T) AnnotationParser.annotationForMap(classz, map);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

import java.io.Serializable;
import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.javatao.jkami.ContextBeanHolder;
import com.javatao.jkami.JkException;
import com.javatao.jkami.Page;
import com.javatao.jkami.RunConfing;
import com.javatao.jkami.jdbc.BeanListHandle;
import com.javatao.jkami.jdbc.JdbcTypesUtils;
import com.javatao.jkami.jdbc.MapListHandle;
import com.javatao.jkami.jdbc.NumberHandle;
import com.javatao.jkami.jdbc.ResultHandle;
import com.javatao.jkami.utils.ExceptionUtils;
import com.javatao.jkami.utils.FKParse;
import com.javatao.jkami.utils.JkBeanUtils;
import com.javatao.jkami.utils.SqlUtils;

package com.javatao.jkami.support;




/**
 * jdbc包装数据
 * 
 * @author tao
 */
public class DataMapper {
    private static DataMapper mapper;
    private static final Log logger = LogFactory.getLog(DataMapper.class);
    private static final String DEFAULT_BEAN = "this";
    private static final String EMPTY = "";
    private static final String SEMICOLON = ";";
    /**
     * 数据库类型
     */
    public static final String DATABSE_TYPE_MYSQL = "mysql";
    public static final String DATABSE_TYPE_POSTGRE = "postgresql";
    public static final String DATABSE_TYPE_ORACLE = "oracle";
    public static final String DATABSE_TYPE_SQLSERVER = "sqlserver";
    /**
     * 分页SQL
     */
    // mysql select * from ( {0} ) page_tab limit {1},{2}
    private static final String MYSQL_SQL = "select * from ( {0} ) page_kami_tab limit ?,?";
    // postgresql {2} offset {1}
    private static final String POSTGRE_SQL = "select * from ( {0} ) page_kami_tab limit ? offset ?";
    // oracle where rownum <= {1}) where rownum_>{2}
    private static final String ORACLE_SQL = "select * from (select row_.*,rownum rownum_ from ({0}) row_ where rownum <= ?) where rownum_> ? ";
    private static final String SQLSERVER_SQL = "select * from ( select row_number() over(order by tempColumn) tempRowNumber, * from (select top ? tempColumn = 0, {0} ) t ) tt where tempRowNumber > ? "; // sqlserver
    private static final String COUNT_SQL = "select count(1) from ( {0} ) conut_kami_tab"; // count_sql
    // oracle 序列查询
    private static final String SEQUENCE_SQL = "select {0}.nextval from dual"; // sequence_sql
    private static final Pattern pat = Pattern.compile(":[ tnx0Bfr]*[a-z.A-Z]+");
    private static final String numberRegex = "^:\\d+$";

    /**
     * 获取 Connection
     * 
     * @return Connection
     */
    private Connection getCon() {
        return RunConfing.getConfig().getConnection();
    }

    /**
     * 释放连接
     * 
     * @param con
     *            Connection
     */
    private void doReleaseConnection(Connection con) {
        RunConfing.getConfig().doReleaseConnection(con);
    }

    /**
     * 获取 DataMapper 单例
     * 
     * @return DataMapper
     */
    public static DataMapper getMapper() {
        if (mapper == null) {
            mapper = new DataMapper();
        }
        return mapper;
    }

    /**
     * 设置预编译值
     * 
     * @param ps
     *            PreparedStatement
     * @param args
     *            参数
     * @throws SQLException
     *             SQLException
     */
    private void setPSValue(PreparedStatement ps, Object... args) throws SQLException {
        if (args != null && args.length > 0) {
            if (args[0] instanceof Collection) {
                args = ((Collection<?>) args[0]).toArray();
            }
            for (int i = 0; i < args.length; i++) {
                Object value = args[i];
                int index = i + 1;
                psValue(ps, index, value);
                if (logger.isDebugEnabled()) {
                    logger.debug("params[" + i + ":" + value + "]");
                }
            }
        }
    }

    /**
     * 设置预编译值
     * 
     * @param ps
     *            PreparedStatement
     * @param entity
     *            实体
     * @return 字段数量
     */
    private int setPSEntityValue(PreparedStatement ps, Object entity) {
        try {
            Class<?> classType = entity.getClass();
            List<String> fileds = SqlUtils.getEntityAttrMp(classType);
            for (int i = 0; i < fileds.size(); i++) {
                String fd = fileds.get(i);
                Object value = JkBeanUtils.getPropertyValue(entity, fd);
                int index = i + 1;
                if (value == null) {
                    ps.setNull(index, JdbcTypesUtils.getJdbcType(value));
                } else {
                    psValue(ps, index, value);
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("params[" + i + ":" + value + "]");
                }
            }
            return fileds.size();
        } catch (Exception e) {
            throw ExceptionUtils.runtimeException(e);
        }
    }

    /**
     * 参数设置
     * 
     * @param ps
     *            PreparedStatement
     * @param index
     *            下标
     * @param value
     *            参数
     * @throws SQLException
     *             异常
     */
    private void psValue(PreparedStatement ps, int index, Object value) throws SQLException {
        if (value instanceof Date) {
            ps.setTimestamp(index, new java.sql.Timestamp(((Date) value).getTime()));
        } else if (value instanceof Collection) {
            Collection<?> coll = (Collection<?>) value;
            Connection conn = RunConfing.getConfig().getConnection();
            String jdbcType = JdbcTypesUtils.getJdbcType(coll);
            Array array = conn.createArrayOf(jdbcType, coll.toArray());
            ps.setArray(index, array);
        } else if (value!=null&&value.getClass().isEnum()) {
            ps.setString(index, ((Enum<?>)value).name());
        } else {
            ps.setObject(index, value);
        }
    }

    /**
     * 保存对象
     * 
     * @param o
     *            对象
     * @return 变更值
     */
    public int save(Object o) {
        RunConfing config = RunConfing.getConfig();
        Connection con = config.getConnection();
        Class<?> classType = o.getClass();
        String sql = SqlUtils.getSqls(classType, SqlUtils.TYPE.INSERT);
        try {
            Object[] key = getTableKey(classType);
            Object idValue = JkBeanUtils.getPropertyValue(o, (String) key[0]);
            String dbType = config.getDbType();
            if (idValue == null) {
                if (dbType.contains(DATABSE_TYPE_ORACLE)) {
                    String s = SqlUtils.getSequenceGeneratorVal(classType);
                    if (s != null) {
                        // 查询序列
                        String sequenceSql = MessageFormat.format(SEQUENCE_SQL, s);

                        idValue = query(sequenceSql, new NumberHandle<Long>());
