package org.nutz.dao.impl.sql; import java.lang.reflect.Array; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.nutz.castor.Castors; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; import org.nutz.dao.entity.Entity; import org.nutz.dao.entity.Record; import org.nutz.dao.sql.Sql; import org.nutz.dao.sql.SqlCallback; import org.nutz.lang.Lang; /** * 仿照Spring JdbcTemplate实现nutz的SqlTemplate,方便sql的调用 * * @author hzl7652(hzl7652@sina.com) */ public class SqlTemplate { private Dao dao; public SqlTemplate() {} public SqlTemplate(Dao dao) { setDao(dao); } public void setDao(Dao dao) { this.dao = dao; } public Dao dao() { return this.dao; } /** * 执行一个SQL更新操作(如插入,更新或删除语句)。 * * @param sql * 包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * * @return SQL 语句所影响的行数 */ public int update(String sql, Map<String, Object> params) { return update(sql, null, params); } /** * 执行一个SQL更新操作(如插入,更新或删除语句)。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * * @return SQL 语句所影响的行数 */ public int update(String sql, Map<String, Object> vars, Map<String, Object> params) { Sql sqlObj = createSqlObj(sql, params); execute(sqlObj, vars, params); return sqlObj.getUpdateCount(); } /** * 执行SQL批量更新操作(如插入,更新或删除语句)。 * * @param sql * 包含变量占位符的SQL * @param batchValues * 批量更新参数集合 * * @return SQL 语句所影响的行数 */ public int batchUpdate(String sql, List<Map<String, Object>> batchValues) { return batchUpdate(sql, null, batchValues); } /** * 执行SQL批量更新操作(如插入,更新或删除语句)。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param batchValues * 批量更新参数集合 * * @return SQL 语句所影响的行数 */ public int batchUpdate(String sql, Map<String, Object> vars, List<Map<String, Object>> batchValues) { Sql sqlObj = null; boolean hasBatchValues = batchValues != null && batchValues.size() > 0; if (hasBatchValues) { sqlObj = createSqlObj(sql, batchValues.get(0)); for (Map<String, Object> params : batchValues) { Map<String, Object> newParams = paramProcess(params); sqlObj.params().putAll(newParams); sqlObj.addBatch(); } dao.execute(sqlObj); } else { sqlObj = createSqlObj(sql, null); execute(sqlObj, vars, null); } return sqlObj.getUpdateCount(); } /** * 执行一个SQL查询操作,结果为一个int形数值。 * <p> * * @param sql * 包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * * @return int数值,当查询为null时返回0 */ public int queryForInt(String sql, Map<String, Object> params) { return queryForInt(sql, null, params); } /** * 执行一个SQL查询操作,结果为一个int形数值。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * * @return int数值,当查询为null时返回0 */ public int queryForInt(String sql, Map<String, Object> vars, Map<String, Object> params) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(Sqls.callback.integer()); execute(sqlObj, vars, params); return sqlObj.getInt(); } /** * 执行一个SQL查询操作,结果为一个long形数值。 * * @param sql * 包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * * @return long数值,当查询为null时返回0 */ public long queryForLong(String sql, Map<String, Object> params) { return queryForLong(sql, null, params); } /** * 执行一个SQL查询操作,结果为一个long形数值。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * * @return long数值,当查询为null时返回0 */ public long queryForLong(String sql, Map<String, Object> vars, Map<String, Object> params) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(Sqls.callback.longValue()); execute(sqlObj, vars, params); Long result = sqlObj.getObject(Long.class); return result == null ? 0 : result; } /** * 执行一个SQL查询操作,结果为给定对象类型的对象,适用于明确SQL查询结果的类型。 * * @param sql * 包含变量占位符的SQL * @param params * 参数map 无参数时,可为null * @param classOfT * 对象类型,SQL查询结果所对应的类型,如Date.class等 * * @return 对象,无查询结果时返回null */ public <T> T queryForObject(String sql, Map<String, Object> params, Class<T> classOfT) { return queryForObject(sql, null, params, classOfT); } /** * 执行一个SQL查询操作,结果为给定对象类型的对象,适用于明确SQL查询结果的类型。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * @param classOfT * 对象类型,SQL查询结果所对应的类型,如Date.class等 * * @return 对象,无查询结果时返回null */ public <T> T queryForObject(String sql, Map<String, Object> vars, Map<String, Object> params, Class<T> classOfT) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(new SqlCallback() { public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { if (null != rs && rs.next()) return rs.getObject(1); return null; } }); execute(sqlObj, vars, params); return sqlObj.getObject(classOfT); } /** * 执行一个SQL查询操作,结果为给定实体的对象。 * * @param sql * 包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * @param entity * 实体类型,无参数时,可为null * * @return 对象,无查询结果时返回null */ public <T> T queryForObject(String sql, Map<String, Object> params, Entity<T> entity) { return queryForObject(sql, null, params, entity); } /** * 执行一个SQL查询操作,结果为给定实体的对象。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * @param entity * 实体类型 * * @return 对象,无查询结果时返回null */ public <T> T queryForObject(String sql, Map<String, Object> vars, Map<String, Object> params, Entity<T> entity) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(Sqls.callback.entity()); sqlObj.setEntity(entity); execute(sqlObj, vars, params); return sqlObj.getObject(entity.getType()); } /** * 执行一个SQL查询操作,结果为Record的对象。 * * @param sql * 包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * * @return Record对象,无查询结果时返回null */ public Record queryForRecord(String sql, Map<String, Object> params) { return queryForRecord(sql, null, params); } /** * 执行一个SQL查询操作,结果为Record的对象。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * @return Record对象,无查询结果时返回null */ public Record queryForRecord(String sql, Map<String, Object> vars, Map<String, Object> params) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(Sqls.callback.record()); execute(sqlObj, vars, params); return sqlObj.getObject(Record.class); } /** * 执行一个SQL查询操作,结果为一组对象。 * * @param sql * 包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * @param entity * 对象类型,无参数时,可为null * * @return 对象列表,无查询结果时返回长度为0的List对象 */ public <T> List<T> query(String sql, Map<String, Object> params, Entity<T> entity) { return query(sql, null, params, entity); } /** * 执行一个SQL查询操作,结果为一组对象。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * @param entity * 对象类型 * * @return 对象列表,无查询结果时返回长度为0的List对象 */ public <T> List<T> query(String sql, Map<String, Object> vars, Map<String, Object> params, Entity<T> entity) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(Sqls.callback.entities()); sqlObj.setEntity(entity); execute(sqlObj, vars, params); return sqlObj.getList(entity.getType()); } /** * 执行一个SQL查询操作,结果为一组对象。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * @param classOfT * 对象类型 * * @return 对象列表,无查询结果时返回长度为0的List对象 */ public <T> List<T> queryForList(String sql, Map<String, Object> vars, Map<String, Object> params, final Class<T> classOfT) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(new SqlCallback() { public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException { List<T> list = new ArrayList<T>(); while (rs.next()) { T result = Castors.me().castTo(rs.getObject(1), classOfT); list.add(result); } return list; } }); execute(sqlObj, vars, params); return sqlObj.getList(classOfT); } /** * 执行一个SQL查询操作,结果为Record对象列表。 * * @param sql * 包含变量占位符的SQL * @param vars * 变量map,无参数时,可为null * @param params * 参数map,无参数时,可为null * * @return Record列表,无查询结果时返回长度为0的List对象 */ public List<Record> queryRecords(String sql, Map<String, Object> vars, Map<String, Object> params) { Sql sqlObj = createSqlObj(sql, params); sqlObj.setCallback(Sqls.callback.records()); execute(sqlObj, vars, params); return sqlObj.getList(Record.class); } /** * 设置sql参数并执行sql。 */ private void execute(Sql sqlObj, Map<String, Object> vars, Map<String, Object> params) { if (vars != null) sqlObj.vars().putAll(vars); if (params != null) { Map<String, Object> newParams = paramProcess(params); sqlObj.params().putAll(newParams); } dao().execute(sqlObj); } /** * 创建Sql对象。 * <p> * 在这里处理Array Collection类型参数,方便SQL IN 表达式的设置 * * @param sql * 包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * * @return Sql对象 */ private Sql createSqlObj(String sql, Map<String, Object> params) { if (params == null) return Sqls.create(sql); String newSql = sqlProcess(sql, params); return Sqls.create(newSql); } /** * 将Array Collection类型参数对应的sql占位符进行处理 * * @param originSql * 原包含变量占位符的SQL * @param params * 参数map,无参数时,可为null * * @return 包含处理IN表达式的sql */ private String sqlProcess(String originSql, Map<String, Object> params) { if (params == null || params.size() == 0) return originSql; String newSql = originSql; for (Entry<String, Object> entry : params.entrySet()) { String paramName = entry.getKey(); Object paramObj = entry.getValue(); if (paramObj.getClass().isArray()) { String inSqlExp = inSqlProcess(paramName, paramObj); newSql = newSql.replaceAll("@" + paramName, inSqlExp); } if (paramObj instanceof Collection) { Collection<?> collection = (Collection<?>) paramObj; Object[] paramVals = Lang.collection2array(collection); String inSqlExp = inSqlProcess(paramName, paramVals); newSql = newSql.replaceAll("@" + paramName, inSqlExp); } } return newSql; } /** * sql参数处理,在这里处理Array Collection类型参数,方便SQL IN 表达式的设置 * * @param params * 参数map,无参数时,可为null * * @return 包含处理IN表达式的sql */ private Map<String, Object> paramProcess(Map<String, Object> params) { if (params == null || params.size() == 0) return null; Map<String, Object> newParams = new HashMap<String, Object>(params); for (Entry<String, Object> entry : params.entrySet()) { String paramName = entry.getKey(); Object paramObj = entry.getValue(); if (paramObj.getClass().isArray()) { inParamProcess(paramName, paramObj, newParams); newParams.remove(paramName); } if (paramObj instanceof Collection) { Collection<?> collection = (Collection<?>) paramObj; Object[] paramVals = Lang.collection2array(collection); inParamProcess(paramName, paramVals, newParams); newParams.remove(paramName); } } return newParams; } private String inSqlProcess(String paramName, Object paramObj) { int len = Array.getLength(paramObj); StringBuilder inSqlExp = new StringBuilder(); for (int i = 0; i < len; i++) { inSqlExp.append("@").append(paramName).append(i).append(","); } inSqlExp.deleteCharAt(inSqlExp.length() - 1); return inSqlExp.toString(); } private void inParamProcess(String paramName, Object paramObj, Map<String, Object> newParams) { int len = Array.getLength(paramObj); for (int i = 0; i < len; i++) { String inParamName = paramName + i; newParams.put(inParamName, Array.get(paramObj, i)); } } }