package com.ketayao.fensy.db; import java.io.Serializable; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ColumnListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import com.ketayao.fensy.cache.CacheManager; import com.ketayao.fensy.exception.DBException; import com.ketayao.fensy.util.ArrayUtils; /** * 数据库查询助手 */ @SuppressWarnings("unchecked") public class QueryHelper { private final static QueryRunner QUERY_RUNNER = new QueryRunner(); @SuppressWarnings("rawtypes") private final static ColumnListHandler COLUMN_LIST_HANDLER = new ColumnListHandler(); @SuppressWarnings("rawtypes") private final static ScalarHandler SCALAR_HANDLER = new ScalarHandler(); // 定义基础类 private final static List<Class<?>> PRIMITIVE_CLASSES = new ArrayList<Class<?>>() { private static final long serialVersionUID = 218015821661758840L; { add(Boolean.class); add(Byte.class); add(Character.class); add(Short.class); add(Integer.class); add(Long.class); add(Float.class); add(Double.class); add(String.class); add(java.util.Date.class); add(java.sql.Date.class); add(java.sql.Timestamp.class); } }; protected final static boolean isPrimitive(Class<?> cls) { return cls.isPrimitive() || PRIMITIVE_CLASSES.contains(cls); } /** * 获取数据库连接 * @return */ public static Connection getConnection() { try { return DBManager.getConnection(); } catch (SQLException e) { throw new DBException(e); } } /** * 读取某个对象 * @param beanClass * @param sql * @param params * @return */ public static <T> T read(Class<T> beanClass, String sql, Object... params) { try { return (T) QUERY_RUNNER.query(getConnection(), sql, isPrimitive(beanClass) ? SCALAR_HANDLER : new BeanHandler<T>(beanClass), params); } catch (SQLException e) { throw new DBException(e); } } /** * 从缓存中,读取某个对象 * @param beanClass * @param cacheRegion * @param key * @param sql * @param params * @return */ public static <T> T readFromCache(Class<T> beanClass, String cacheRegion, Serializable key, String sql, Object... params) { T obj = (T) CacheManager.get(cacheRegion, key); if (obj == null) { obj = read(beanClass, sql, params); CacheManager.put(cacheRegion, key, (Serializable) obj); } return obj; } /** * 对象查询 * @param <T> * @param beanClass * @param sql * @param params * @return */ public static <T> List<T> query(Class<T> beanClass, String sql, Object... params) { try { return (List<T>) QUERY_RUNNER.query(getConnection(), sql, isPrimitive(beanClass) ? COLUMN_LIST_HANDLER : new BeanListHandler<T>(beanClass), params); } catch (SQLException e) { throw new DBException(e); } } /** * 支持缓存的对象查询 * @param <T> * @param beanClass * @param cacheRegion * @param key * @param sql * @param params * @return */ public static <T> List<T> queryFromCache(Class<T> beanClass, String cacheRegion, Serializable key, String sql, Object... params) { List<T> objs = (List<T>) CacheManager.get(cacheRegion, key); if (objs == null) { objs = query(beanClass, sql, params); CacheManager.put(cacheRegion, key, (Serializable) objs); } return objs; } /** * 分页查询 * @param <T> * @param beanClass * @param sql * @param page * @param count * @param params * @return */ public static <T> List<T> querySlice(Class<T> beanClass, String sql, int page, int count, Object... params) { if (page < 0 || count < 0) throw new IllegalArgumentException( "Illegal parameter of 'page' or 'count', Must be positive."); int from = (page - 1) * count; count = (count > 0) ? count : Integer.MAX_VALUE; return query(beanClass, sql + " LIMIT ?,?", ArrayUtils.addAll(params, (Object[]) (new Integer[] { from, count }))); } /** * 支持缓存的分页查询 * @param <T> * @param beanClass * @param cacheRegion * @param key * @param cacheObjCount * @param sql * @param page * @param count * @param params * @return */ public static <T> List<T> querySliceCache(Class<T> beanClass, String cacheRegion, Serializable key, int cacheObjCount, String sql, int page, int count, Object... params) { List<T> objs = (List<T>) CacheManager.get(cacheRegion, key); if (objs == null) { objs = querySlice(beanClass, sql, 1, cacheObjCount, params); CacheManager.put(cacheRegion, key, (Serializable) objs); } if (objs == null || objs.size() == 0) return objs; int from = (page - 1) * count; if (from < 0) return null; if ((from + count) > cacheObjCount)// 超出缓存的范围 return querySlice(beanClass, sql, page, count, params); int end = Math.min(from + count, objs.size()); if (from >= end) return null; return objs.subList(from, end); } /** * 执行统计查询语句,语句的执行结果必须只返回一个数值 * @param sql * @param params * @return */ public static long stat(String sql, Object... params) { try { //Number num = (Number) QUERY_RUNNER.query(getConnection(), sql, SCALAR_HANDLER, params); //return (num != null) ? num.longValue() : -1; Long num = QUERY_RUNNER.query(getConnection(), sql, new ScalarHandler<Long>(), params); return (num != null) ? num.longValue() : -1; } catch (SQLException e) { throw new DBException(e); } } /** * 执行统计查询语句,语句的执行结果必须只返回一个数值 * @param cacheRegion * @param key * @param sql * @param params * @return */ public static long statFromCache(String cacheRegion, Serializable key, String sql, Object... params) { Long value = (Long) CacheManager.get(cacheRegion, key); if (value == null) { value = stat(sql, params); CacheManager.put(cacheRegion, key, value); } return value.longValue(); } /** * 执行INSERT/UPDATE/DELETE语句 * @param sql * @param params * @return */ public static int update(String sql, Object... params) { try { return QUERY_RUNNER.update(getConnection(), sql, params); } catch (SQLException e) { throw new DBException(e); } } /** * 批量执行指定的SQL语句 * @param sql * @param params * @return */ public static int[] batch(String sql, Object[][] params) { try { return QUERY_RUNNER.batch(getConnection(), sql, params); } catch (SQLException e) { throw new DBException(e); } } }