jp.co.golorp.emarf.model.Models.java Source code

Java tutorial

Introduction

Here is the source code for jp.co.golorp.emarf.model.Models.java

Source

/*
 * Apache License, Version 2.0???????
 * ?????????????
 *
 * ??http://www.apache.org/licenses/LICENSE-2.0?????
 *
 * ???????????????
 * ????????
 * ??????????????????????
 *
 * ????????????????????????
 */
package jp.co.golorp.emarf.model;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.BeanProcessor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.RowProcessor;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jp.co.golorp.emarf.constants.AppKey;
import jp.co.golorp.emarf.constants.MessageKeys;
import jp.co.golorp.emarf.constants.model.ModelFieldTypes;
import jp.co.golorp.emarf.exception.ApplicationError;
import jp.co.golorp.emarf.exception.SystemError;
import jp.co.golorp.emarf.generator.BeanGenerator;
import jp.co.golorp.emarf.properties.App;
import jp.co.golorp.emarf.properties.collection.AppSet;
import jp.co.golorp.emarf.sql.Connections;
import jp.co.golorp.emarf.sql.MetaData;
import jp.co.golorp.emarf.sql.info.ColumnInfo;
import jp.co.golorp.emarf.sql.info.TableInfo;
import jp.co.golorp.emarf.sql.relation.RelateColumnMap;
import jp.co.golorp.emarf.util.DateUtil;
import jp.co.golorp.emarf.util.IOUtil;
import jp.co.golorp.emarf.util.LogUtil;
import jp.co.golorp.emarf.util.ModelUtil;
import jp.co.golorp.emarf.util.StringUtil;

/**
 * IO
 *
 * @author oukuf@golorp
 */
public final class Models {

    /** LOG */
    private static final Logger LOG = LoggerFactory.getLogger(Models.class);

    /** ?? */
    private static final String ROW_MAX = App.get(AppKey.MODELS_ROW_MAX);

    /** ? */
    public static final String ID_SUFFIX = App.get(AppKey.MODELS_ID_SUFFIX);

    /** ??Set */
    public static final String SEQ_SUFFIX = App.get(AppKey.MODELS_SEQ_SUFFIX);

    /**  */
    private static final String ORACLE_SEQUENCE_PREFIX = App.get(AppKey.MODELS_ORACLE_SEQUENCE_PREFIX);

    /**  */
    private static final String ORACLE_SEQUENCE_SUFFIX = App.get(AppKey.MODELS_ORACLE_SEQUENCE_SUFFIX);

    /** ??? */
    public static final AppSet<String> AINT_INSERT_SET = App.getSet(AppKey.MODELS_AINT_INSERTS);

    /** ??? */
    public static final AppSet<String> AINT_UPDATE_SET = App.getSet(AppKey.MODELS_AINT_UPDATES);

    /**  */
    public static final Map<String, String> AUTO_INSERT_MAP = App.getMap(AppKey.MODELS_AUTO_INSERT_VALUES);

    /**  */
    public static final Map<String, String> AUTO_UPDATE_MAP = App.getMap(AppKey.MODELS_AUTO_UPDATE_VALUES);

    /**  */
    private static PagingBy pagingBy = null;

    /**
     * ??
     *
     * @author oukuf@golorp
     */
    public enum PagingBy {

        /** limit?mysql?? */
        limit,

        /** rownum?oracle?? */
        rownum
    }

    /**
     * 
     */
    private Models() {
    }

    /**
     * insert
     *
     * @param model
     *            ?
     * @return ??
     */
    public static Model create(final Model model) {

        // ??
        String modelName = model.getClass().getSimpleName();

        // 
        TableInfo tableInfo = MetaData.getTableInfo(modelName);
        if (tableInfo == null) {
            throw new SystemError(MessageKeys.ABEND_DATA_INSERT, modelName);
        }

        // ??
        String tableName = tableInfo.getTableName();

        // 
        Set<String> primaryKeys = tableInfo.getPrimaryKeys();

        // OracleSequence?????
        if (primaryKeys.size() == 1) {
            fillByOracleSequence(model, tableName, primaryKeys.iterator().next());
        }

        // ??
        Set<String> primaryPropertyNames = ModelUtil.getPrimaryPropertyNames(modelName);
        if (primaryPropertyNames != null) {

            // ???
            Iterator<String> iPrimaryPropertyNames = primaryPropertyNames.iterator();
            String primaryPropertyName = iPrimaryPropertyNames.next();
            Object o = model.get(primaryPropertyName);
            if (o != null) {

                // ???????
                boolean isExistAllKey = true;

                // criteria???
                Criteria c = Criteria.equal(modelName, primaryPropertyName, o);

                // criteria????
                while (iPrimaryPropertyNames.hasNext()) {
                    primaryPropertyName = iPrimaryPropertyNames.next();
                    o = model.get(primaryPropertyName);
                    if (o == null) {
                        isExistAllKey = false;
                        break;
                    }
                    c.eq(primaryPropertyName, o);
                }

                // ??????????????
                if (isExistAllKey && Models.getModel(modelName, c) != null) {
                    throw new ApplicationError(MessageKeys.ERRORS_DATA_DUPLICATE);
                }
            }
        }

        /*
         * ?
         */

        Statement statement = Models.getStatement(ModelFieldTypes.GET_INSERT_STATEMENT, model);
        if (Models.regist(statement.getSql(), statement.getParams()) != 1) {
            throw new SystemError(MessageKeys.ABEND_DATA_INSERT, tableInfo.getTableMei());
        }

        /*
         * ???
         */

        // ????
        for (String primaryPropertyName : primaryPropertyNames) {

            // ????
            if (model.get(primaryPropertyName) != null) {
                continue;
            }

            // ????
            ColumnInfo primaryKeyInfo = tableInfo.getColumnInfo(primaryPropertyName);
            String primaryKeyName = primaryKeyInfo.getColumnName();

            if (primaryPropertyName.endsWith(Models.ID_SUFFIX)) {
                // AUTO_INCREMENT?ID?

                String sql = "select last_insert_id() as " + primaryKeyName + " from " + tableName;
                List<Map<String, Object>> datas = Models.getDatas(sql);
                if (datas == null) {
                    continue;
                }

                Map<String, Object> data = datas.get(0);
                BigInteger value = (BigInteger) data.get(primaryPropertyName);
                if (value.intValue() >= 0) {
                    model.set(primaryPropertyName, value.intValue());
                }

            } else if (primaryPropertyName.endsWith(Models.SEQ_SUFFIX)) {
                // ??

                StringBuilder sb = new StringBuilder();
                List<Object> params = new ArrayList<Object>();

                // ?????????????
                Set<String> primaryPropertyNames2 = ModelUtil.getPrimaryPropertyNames(modelName);
                for (String primaryPropertyName2 : primaryPropertyNames2) {

                    // ???
                    if (primaryPropertyName2.equals(primaryPropertyName)) {
                        break;
                    }

                    // ????where??
                    if (sb.length() > 0) {
                        sb.append(" and");
                    }
                    ColumnInfo primaryKeyInfo2 = tableInfo.getColumnInfo(primaryPropertyName2);
                    String columnName2 = primaryKeyInfo2.getColumnName();
                    Object columnValue2 = model.get(primaryPropertyName2);
                    sb.append(" ").append(columnName2).append(" = ?");
                    params.add(columnValue2);
                }

                // ?
                String sql = "SELECT MAX(" + primaryKeyName + ") AS " + primaryKeyName + " from " + tableName
                        + " WHERE " + sb.toString();
                List<Map<String, Object>> datas = Models.getDatas(sql, params.toArray());
                if (datas == null) {
                    continue;
                }

                // ??????????????????????0?
                Map<String, Object> data = datas.get(0);
                Object value = data.get(primaryPropertyName);
                if (value != null) {
                    model.set(primaryPropertyName, value);
                } else {
                    model.set(primaryPropertyName, 0);
                }
            }
        }

        return Models.refer(model);
    }

    /**
     * 
     *
     * @param model
     *            ?
     * @return ??
     */
    public static Model refer(final Model model) {
        String modelName = model.getClass().getSimpleName();
        Statement statement = Models.getStatement(ModelFieldTypes.GET_SELECT_STATEMENT, model);
        return Models.getBean(modelName, statement.getSql(), statement.getParams());
    }

    /**
     * update
     *
     * @param model
     *            ?
     */
    public static void update(final Model model) {
        Statement statement = Models.getStatement(ModelFieldTypes.GET_UPDATE_STATEMENT, model);
        if (Models.regist(statement.getSql(), statement.getParams()) != 1) {
            String modelName = model.getClass().getSimpleName();
            String tableMei = MetaData.getTableInfo(modelName).getTableMei();
            throw new SystemError(MessageKeys.ABEND_DATA_UPDATE, tableMei);
        }
    }

    /**
     * delete
     *
     * @param model
     *            ?
     */
    public static void delete(final Model model) {
        Statement statement = Models.getStatement(ModelFieldTypes.GET_DELETE_STATEMENT, model);
        if (Models.regist(statement.getSql(), statement.getParams()) != 1) {
            String modelName = model.getClass().getSimpleName();
            String tableMei = MetaData.getTableInfo(modelName).getTableMei();
            throw new SystemError(MessageKeys.ABEND_DATA_DELETE, tableMei);
        }
    }

    /**
     * @param modelName
     *            truncate???
     */
    public static void truncate(final String modelName) {

        TableInfo tableInfo = MetaData.getTableInfo(modelName);
        if (tableInfo == null) {
            throw new SystemError(MessageKeys.ABEND_DATA_DELETE, modelName);
        }

        String tableName = tableInfo.getTableName();
        try {
            Models.regist("TRUNCATE TABLE " + tableName);
        } catch (Exception e) {
            // truncate?????sqlite??
            Models.regist("DELETE FROM " + tableName);
        }
    }

    /**
     * ?
     *
     * @param modelName
     *            ??
     * @param c
     *            ?
     * @return 
     */
    public static int count(final String modelName, final Criteria c) {

        // TODO ??????????
        // if (c == null) {
        // return 0;
        // }

        Statement where = getWhere(modelName, c);

        String selectSQL = "SELECT COUNT(*) CNT FROM " + where.getSql();

        Object[] params = where.getParams();

        List<Map<String, Object>> datas = getDatas(selectSQL, params);

        Map<String, Object> data = datas.get(0);

        return Integer.parseInt(data.get("cnt").toString());
    }

    /**
     * criteria??select
     *
     * @param modelName
     *            ??
     * @param c
     *            ?
     * @return 
     */
    public static Model getModel(final String modelName, final Criteria c) {

        List<Model> models = getModels(modelName, c, null, null);

        if (models == null || models.size() == 0) {
            return null;
        }

        if (models.size() > 1) {
            throw new SystemError(MessageKeys.ERRORS_DATA_PLURAL);
        }

        return (Model) models.get(0);
    }

    /**
     * criteria?select
     *
     * @param modelName
     *            ??
     * @param c
     *            ?
     * @return ?
     */
    public static List<Model> getModels(final String modelName, final Criteria c) {
        return getModels(modelName, c, null, null);
    }

    /**
     * criteria?select
     *
     * @param modelName
     *            ??
     * @param c
     *            Criteria
     * @param rows
     *            ?
     * @param page
     *            ??
     * @return ?
     */
    public static List<Model> getModels(final String modelName, final Criteria c, final String rows,
            final String page) {

        // ?????
        String rowsValue = ROW_MAX;
        if (rows != null) {
            rowsValue = rows;
        }

        // ?????
        String pageValue = "1";
        if (page != null) {
            pageValue = page;
        }

        // where?????
        Statement where = getWhere(modelName, c);
        if (where == null) {
            return null;
        }

        String sql = "SELECT * FROM " + where.getSql();

        int r = Integer.valueOf(rowsValue);
        int p = Integer.valueOf(pageValue);
        int offset = r * (p - 1);

        if (pagingBy == null || pagingBy == PagingBy.limit) {
            try {
                sql += " limit " + offset + ", " + rowsValue;
                List<Model> beans = getBeans(modelName, sql, where.getParams());
                pagingBy = PagingBy.limit;
                return beans;
            } catch (Exception e) {
            }
        }

        if (pagingBy == null || pagingBy == PagingBy.rownum) {
            try {
                int f = offset + 1;
                int t = offset + r;
                sql = "SELECT * FROM (SELECT ROWNUM AS RNO, A.* FROM (" + sql + ") A) WHERE RNO BETWEEN " + f
                        + " AND " + t;
                List<Model> beans = getBeans(modelName, sql, where.getParams());
                pagingBy = PagingBy.rownum;
                return beans;
            } catch (Exception e) {
            }
        }

        return null;
    }

    /**
     * ??oracle??
     *
     * @param model
     *            Model
     * @param tableName
     *            ???
     * @param columnName
     *            ?????
     */
    private static void fillByOracleSequence(final Model model, final String tableName, final String columnName) {

        StringBuilder sb = new StringBuilder("SELECT ");

        if (ORACLE_SEQUENCE_PREFIX != null) {
            sb.append(ORACLE_SEQUENCE_PREFIX);
        }

        sb.append(tableName).append("_").append(columnName);

        if (ORACLE_SEQUENCE_SUFFIX != null) {
            sb.append(ORACLE_SEQUENCE_SUFFIX);
        }

        sb.append(".NEXTVAL AS ").append(columnName).append(" FROM DUAL");

        try {
            List<Map<String, Object>> datas = Models.getDatas(sb.toString());
            Map<String, Object> data = datas.get(0);
            String propertyName = StringUtil.toCamelCase(columnName);
            Object value = data.get(propertyName);
            if (value != null) {
                model.set(propertyName, value);
            }
        } catch (Exception e) {
            LOG.trace(tableName + "." + columnName + " is not use Oracle Sequence.");
        }
    }

    /**
     * ??????????
     *
     * @param <T>
     *            
     * @param bean
     *            ??bean
     */
    private static <T> void cp2org(final T bean) {
        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.getName().startsWith(BeanGenerator.ORG_PREFIX)) {
                try {
                    String orgName = field.getName();
                    String propertyName = orgName.replaceFirst(BeanGenerator.ORG_PREFIX, "");
                    Field property = clazz.getDeclaredField(propertyName);
                    field.setAccessible(true);
                    property.setAccessible(true);
                    Object value = property.get(bean);
                    field.set(bean, value);
                } catch (Exception e) {
                    throw new SystemError(e);
                }
            }
        }
    }

    /**
     * ???
     *
     * @param sql
     *            ?sql
     * @param params
     *            sql?
     * @return ?
     */
    private static int regist(final String sql, final Object... params) {

        Date sysDate = DateUtil.getDate();

        for (int i = 0; i < params.length; i++) {
            Object param = params[i];
            if (StringUtil.isNotBlank(param) && param.toString().equals("@{sysDate}")) {
                params[i] = new Timestamp(sysDate.getTime());
            }
        }

        statementLog(getRawSql(sql, params));

        QueryRunner runner = new QueryRunner();
        Connection cn = Connections.get();
        try {
            return runner.update(cn, sql, params);
        } catch (SQLException e) {
            throw new SystemError(e);
        }
    }

    /**
     * crud?
     *
     * @param kind
     *            ?????
     * @param model
     *            ??
     * @return sql??set
     */
    private static Statement getStatement(final ModelFieldTypes kind, final Model model) {

        Class<?> clazz = model.getClass();

        Method method = null;
        try {
            method = clazz.getMethod(kind.toString(), clazz);
        } catch (NoSuchMethodException | SecurityException e) {
            throw new SystemError(e);
        }

        Object o = null;
        try {
            o = method.invoke(clazz, model);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            throw new SystemError(e);
        }

        return (Statement) o;
    }

    /**
     * criteria???join???sql?
     *
     * @param modelName
     *            ??
     * @param c
     *            ?
     * @return sql??set
     */
    private static Statement getWhere(final String modelName, final Criteria c) {

        Criteria criteria = c;

        if (StringUtil.isNotBlank(BeanGenerator.DELETE_F)) {

            String deleteF = StringUtil.toCamelCase(BeanGenerator.DELETE_F);

            if (MetaData.getColumnInfo(modelName, deleteF) != null) {
                Criteria cDeleteF = Criteria.notEqual(modelName, deleteF, "1").or().eq(deleteF, null);
                if (criteria == null) {
                    criteria = cDeleteF;
                } else {
                    criteria.and(cDeleteF);
                }
            }

            if (criteria != null) {
                for (String modelName2 : criteria.getModels()) {
                    if (!modelName.equals(modelName2)) {
                        if (MetaData.getColumnInfo(modelName2, deleteF) != null) {
                            Criteria cDeleteF = Criteria.notEqual(modelName2, deleteF, "1").or().eq(deleteF, null);
                            if (criteria == null) {
                                criteria = cDeleteF;
                            } else {
                                criteria.and(cDeleteF);
                            }
                        }
                    }
                }
            }
        }

        StringBuilder sql = new StringBuilder();

        TableInfo tableInfo = MetaData.getTableInfo(modelName);
        if (tableInfo == null) {
            return null;
        }

        String tableName = tableInfo.getTableName();

        sql.append(tableName);

        // ??
        if (criteria != null) {

            for (String modelName2 : criteria.getModels()) {

                if (modelName.equals(modelName2)) {
                    continue;
                }

                TableInfo tableInfo2 = MetaData.getTableInfo(modelName2);

                String tableName2 = tableInfo2.getTableName();

                sql.append(" INNER JOIN ").append(tableName2);

                List<RelateColumnMap> relateColumnsList = ModelUtil.getRelateProperties(modelName, modelName2);
                if (relateColumnsList != null) {

                    sql.append(" ON ");

                    StringBuilder sql2 = new StringBuilder();

                    for (RelateColumnMap relateColumns : relateColumnsList) {

                        for (Entry<String, String> relateColumn : relateColumns.entrySet()) {

                            String propertyName = relateColumn.getKey();
                            String propertyName2 = relateColumn.getValue();

                            ColumnInfo columnInfo = tableInfo.getColumnInfo(propertyName);
                            ColumnInfo columnInfo2 = tableInfo2.getColumnInfo(propertyName2);

                            String columnName = columnInfo.getColumnName();
                            String columnName2 = columnInfo2.getColumnName();

                            if (sql2.length() > 0) {
                                sql2.append(" AND ");
                            }

                            sql2.append(tableName).append(".").append(columnName).append(" = ").append(tableName2)
                                    .append(".").append(columnName2);
                        }
                    }

                    sql.append(sql2);
                }
            }
        }

        List<Object> params = new ArrayList<Object>();

        if (criteria != null) {
            if (criteria.is()) {
                sql.append(" WHERE ");
                params.addAll(criteria.toParameter());
            }
            sql.append(criteria);
        }

        return new Statement(sql.toString(), params.toArray(new Object[params.size()]));
    }

    /**
     * Model?????IO
     *
     * @param sql
     *            sql
     * @param params
     *            params
     * @return List
     */
    private static List<Map<String, Object>> getDatas(final String sql, final Object... params) {

        // ?SQL?
        String rawSql = getRawSql(sql, params);

        // SQL??????
        List<Map<String, Object>> datas = ModelsCache.get(rawSql);
        if (datas != null) {
            return datas;
        }

        // 
        statementLog(rawSql);

        // ?
        PreparedStatement ps = null;
        try {
            ps = Connections.get().prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                ps.setString(i + 1, String.valueOf(params[i]));
            }

            // ??
            datas = new ArrayList<Map<String, Object>>();

            ResultSet rs = null;
            try {

                // ???
                rs = ps.executeQuery();
                while (rs.next()) {

                    // ?
                    Map<String, Object> data = new LinkedHashMap<String, Object>();

                    // ResultSet?META?
                    ResultSetMetaData meta = rs.getMetaData();

                    // META????
                    int columnCount = meta.getColumnCount();
                    for (int i = 1; i <= columnCount; i++) {

                        // ???
                        String columnName = meta.getColumnName(i);

                        // ???
                        String propertyName = StringUtil.toCamelCase(columnName);

                        String key = propertyName;
                        if (data.containsKey(propertyName)) {
                            String modelName = StringUtil.toUpperCamelCase(meta.getTableName(i));
                            key = modelName + "." + propertyName;
                        }

                        // 
                        data.put(key, rs.getObject(columnName));
                    }

                    // 
                    datas.add(data);
                }

            } catch (SQLException e) {
                throw new SystemError(e);
            } finally {
                IOUtil.closeQuietly(rs);
            }

        } catch (SQLException e) {
            throw new SystemError(e);
        } finally {
            IOUtil.closeQuietly(ps);
        }

        // SQL?
        // ModelsCache.set(rawSql, datas);

        return datas;
    }

    /**
     * ???IO
     *
     * @param <T>
     *            ??
     * @param modelName
     *            ??
     * @param sql
     *            ?sql
     * @param params
     *            sql
     * @return ???
     */
    private static <T> List<T> getBeans(final String modelName, final String sql, final Object... params) {

        Class<?> type = ModelUtil.getBlankModel(modelName).getClass();

        RowProcessor rp = getRowProcessor(modelName);

        @SuppressWarnings({ "rawtypes", "unchecked" })
        ResultSetHandler rsh = new BeanListHandler(type, rp);

        List<T> list = query(sql, rsh, params);
        for (T bean : list) {
            cp2org(bean);
        }

        return list;
    }

    /**
     * ???IO
     *
     * @param <T>
     *            ??
     * @param modelName
     *            ??
     * @param sql
     *            ?sql
     * @param params
     *            sql
     * @return ??
     */
    private static <T> T getBean(final String modelName, final String sql, final Object... params) {

        Class<?> type = ModelUtil.getBlankModel(modelName).getClass();

        RowProcessor rp = getRowProcessor(modelName);

        @SuppressWarnings({ "rawtypes", "unchecked" })
        ResultSetHandler rsh = new BeanHandler(type, rp);

        T bean = query(sql, rsh, params);
        if (bean != null) {
            cp2org(bean);
        }

        return bean;
    }

    /**
     * 
     *
     * @param rawSql
     *            ?sql
     */
    private static void statementLog(final String rawSql) {

        LOG.info("<query> " + rawSql);

        LogUtil.callerLog();
    }

    /**
     * ?????sql??
     *
     * @param sql
     *            sql
     * @param params
     *            
     * @return ???sql
     */
    private static String getRawSql(final String sql, final Object... params) {

        String query = sql;

        for (Object param : params) {
            query = query.replaceFirst("\\?", "'" + String.valueOf(param).replaceAll("\\\\", "\\\\\\\\") + "'");
        }

        return query;
    }

    /**
     * dbutils?
     *
     * @param modelName
     *            ??
     * @return RowProcessor
     */
    private static RowProcessor getRowProcessor(final String modelName) {

        Map<String, String> mapping = new LinkedHashMap<String, String>();

        Map<String, String> propertyMeis = ModelUtil.getPropertyMeis(modelName);

        TableInfo tableInfo = MetaData.getTableInfo(modelName);

        for (String propertyName : propertyMeis.keySet()) {
            ColumnInfo columnInfo = tableInfo.getColumnInfo(propertyName);
            String columnName = columnInfo.getColumnName();
            mapping.put(columnName, propertyName);
        }

        BeanProcessor convert = new BeanProcessor(mapping);

        return new BasicRowProcessor(convert);
    }

    /**
     * IO
     *
     * @param <T>
     *            ??
     * @param sql
     *            sql
     * @param rsh
     *            ResultSetHandler
     * @param params
     *            
     * @return ????
     */
    @SuppressWarnings("unchecked")
    private static <T> T query(final String sql, final ResultSetHandler<?> rsh, final Object... params) {

        String rawSql = getRawSql(sql, params);

        T result = (T) ModelsCache.get(rawSql);
        if (result != null) {
            return result;
        }

        statementLog(rawSql);

        QueryRunner runner = new QueryRunner();

        Connection cn = Connections.get();

        try {

            if (params == null || params.length == 0) {
                result = (T) runner.query(cn, sql, rsh);
            } else {
                result = (T) runner.query(cn, sql, rsh, params);
            }

            ModelsCache.set(rawSql, result);

            return result;

        } catch (Exception e) {
            throw new SystemError(e);
        }

    }

}