OSChina底层数据库操作的类(QueryHelper)源码

Stella981
• 阅读 763

OSChina 使用的是 dbutils 这个JDBC的封装类库来进行数据库操作。而 QueryHelper 则是在 dbutils 的基础上进行一级简单的封装,提供一些常用的数据库操作方法和对数据缓存的支持。OSChina底层数据库操作的类(QueryHelper)源码

红薯...QueryHelper 代码如下:

package my.db;

import java.io.Serializable;
import java.math.BigInteger;
import java.sql.*;
import java.util.*;

import my.cache.CacheManager;
import net.oschina.Configurations;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.apache.commons.lang.ArrayUtils;

/**
 * 数据库查询助手
 * @author Winter Lau<br> */
@SuppressWarnings("unchecked")
public class QueryHelper {
    
    private final static QueryRunner _g_runner = new QueryRunner();
    private final static ColumnListHandler _g_columnListHandler = new ColumnListHandler(){
        @Override
        protected Object handleRow(ResultSet rs) throws SQLException {
            Object obj = super.handleRow(rs);
            if(obj instanceof BigInteger)
                return ((BigInteger)obj).longValue();
            return obj;
        }
        
    };
    private final static ScalarHandler _g_scaleHandler = new ScalarHandler(){
        @Override
        public Object handle(ResultSet rs) throws SQLException {
            Object obj = super.handle(rs);
            if(obj instanceof BigInteger)
                return ((BigInteger)obj).longValue();
            return obj;
        }        
    };
    
    private final static List<Class<?>> PrimitiveClasses = new ArrayList<Class<?>>(){{
        add(Long.class);
        add(Integer.class);
        add(String.class);
        add(java.util.Date.class);
        add(java.sql.Date.class);
        add(java.sql.Timestamp.class);
    }};
    
    private final static boolean _IsPrimitive(Class<?> cls) {
        return cls.isPrimitive() || PrimitiveClasses.contains(cls) ;
    }
    
    /**
     * 获取数据库连接
     * @return
     */
    public static Connection getConnection() {
        try{
            return Configurations.getConnection();
        }catch(SQLException e){
            throw new DBException(e);
        }
    }

    /**
     * 读取某个对象
     * @param sql
     * @param params
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static <T> T read(Class<T> beanClass, String sql, Object...params) {
        try{
            return (T)_g_runner.query(getConnection(), sql, _IsPrimitive(beanClass)?_g_scaleHandler:new BeanHandler(beanClass), params);
        }catch(SQLException e){
            throw new DBException(e);
        }
    }
    
    public static <T> T read_cache(Class<T> beanClass, String cache, Serializable key, String sql, Object...params) {
        T obj = (T)CacheManager.get(cache, key);
        if(obj == null){
            obj = read(beanClass, sql, params);
            CacheManager.set(cache, key, (Serializable)obj);
        }
        return obj;
    }
    
    /**
     * 对象查询
     * @param <T>
     * @param beanClass
     * @param sql
     * @param params
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static <T> List<T> query(Class<T> beanClass, String sql, Object...params) {
        try{
            return (List<T>)_g_runner.query(getConnection(), sql, _IsPrimitive(beanClass)?_g_columnListHandler:new BeanListHandler(beanClass), params);
        }catch(SQLException e){
            throw new DBException(e);
        }
    }

    /**
     * 支持缓存的对象查询
     * @param <T>
     * @param beanClass
     * @param cache_region
     * @param key
     * @param sql
     * @param params
     * @return
     */
    public static <T> List<T> query_cache(Class<T> beanClass, String cache_region, Serializable key, String sql, Object...params) {        
        List<T> objs = (List<T>)CacheManager.get(cache_region, key);
        if(objs == null){
            objs = query(beanClass, sql, params);
            CacheManager.set(cache_region, key, (Serializable)objs);
        }
        return objs;
    }
    
    /**
     * 分页查询
     * @param <T>
     * @param beanClass
     * @param sql
     * @param page
     * @param count
     * @param params
     * @return
     */
    public static <T> List<T> query_slice(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, new Integer[]{from,count}));        
    }
    
    /**
     * 支持缓存的分页查询
     * @param <T>
     * @param beanClass
     * @param cache
     * @param cache_key
     * @param cache_obj_count
     * @param sql
     * @param page
     * @param count
     * @param params
     * @return
     */
    public static <T> List<T> query_slice_cache(Class<T> beanClass, String cache, Serializable cache_key, int cache_obj_count, String sql, int page, int count, Object...params) {
        List<T> objs = (List<T>)CacheManager.get(cache, cache_key);
        if(objs == null) {
            objs = query_slice(beanClass, sql, 1, cache_obj_count, params);
            CacheManager.set(cache, cache_key, (Serializable)objs);
        }
        if(objs == null || objs.size()==0)
            return objs;
        int from = (page - 1) * count;
        if(from < 0)
            return null;
        if((from+count) > cache_obj_count)//超出缓存的范围
            return query_slice(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)_g_runner.query(getConnection(), sql, _g_scaleHandler, params);
            return (num!=null)?num.longValue():-1;
        }catch(SQLException e){
            throw new DBException(e);
        }
    }

    /**
     * 执行统计查询语句,语句的执行结果必须只返回一个数值
     * @param cache_region
     * @param key
     * @param sql
     * @param params
     * @return
     */
    public static long stat_cache(String cache_region, Serializable key, String sql, Object...params) {
        Number value = (Number)CacheManager.get(cache_region, key);
        if(value == null){
            value = stat(sql, params);
            CacheManager.set(cache_region, key, value);
        }
        return value.longValue();
    }

    /**
     * 执行INSERT/UPDATE/DELETE语句
     * @param sql
     * @param params
     * @return
     */
    public static int update(String sql, Object...params) {
        try{
            return _g_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 _g_runner.batch(getConnection(), sql, params);
        }catch(SQLException e){
            throw new DBException(e);
        }
    }
}

该类主要提供包括查询列表、查询列表分页、查询单条记录、统计等方法的封装。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这