基于ORMLite封装的数据库操作工具类,分页查询就是这么简单

EasyDB

基于ORMLite封装的数据库操作工具类——致力于最简洁的数据库操作API

功能点

  • 支持自定义数据库路径:SD卡或系统
  • 支持主键、索引
  • 支持增、删、改、查
  • 支持多条件查询、排序、统计、清空、是否存在
  • 支持批处理、数据库事务操作
  • 支持模糊查询like、between、equal、>、<、>=、<=、<>
  • 支持分页查询,分页查询只需要定义每页条数即可
  • 支持批量处理
  • 支持异步任务操作
  • 支持数据库升级,使数据库升级更为简洁
  • 完整的日志与异常处理
  • 后续优化中...

引用方式

Maven

<dependency>
  <groupId>com.zhousf.lib</groupId>
  <artifactId>easydb</artifactId>
  <version>1.7.0</version>
  <type>pom</type>
</dependency>

Gradle

compile 'com.zhousf.lib:easydb:1.7.0'

提交记录

  • 2016-12-15 项目提交
  • 2016-12-20 增加批处理、事务操作功能
  • 2016-12-23 增加异步任务功能
  • 2016-12-27 扩展更新、删除操作
  • 2017-05-23 优化结构,采用动态代理方式
  • 2017-06-12 增加自定义数据库路径功能

项目演示DEMO

项目中已包含所有支持业务的demo,详情请下载项目参考源码。

Application中配置

EasyDBConfig.init()
        .showDBLog(true)//显示数据库操作日志
        .setLogTAG("EASY_DB")//日志显示标识
        .build();

自定义数据库单例

单例模式防止频繁打开关闭数据库,从而导致数据操作性能下降,甚至出现一些异常错误。
自定义数据库单例继承BaseDBHelper,BaseDBHelper进行数据库操作的缓存管理

// 数据库辅助类
public class EasyDBHelper extends BaseDBHelper {

    //版本号
    private static final int DB_VERSION = 2;

    //数据库存放路径
    private static final String DB_PATH = Environment.getExternalStorageDirectory() + "/easy_db";

    //数据库名称
    private static final String DB_NAME = "easy_android.db";

    //数据表清单-数据库与表的关系更直观
    private static final Class<?>[] tables = {
        SimpleData.class
    };

    private static EasyDBHelper helper = null;

    public static EasyDBHelper get(){
        if(null == helper){
            synchronized (EasyDBHelper.class){
                if(null == helper){
                    helper = new EasyDBHelper();
                }
            }
        }
        return helper;
    }

    private EasyDBHelper() {
        //系统数据库
        //super(BaseApplication.getApplication(), null,DB_NAME,DB_VERSION,tables);
        //SD卡数据库
        super(BaseApplication.getApplication(), DB_PATH,DB_NAME,DB_VERSION,tables);
    }

    @Override
    protected BaseDBHelper initHelper() {
        return get();
    }

    @Override
    protected boolean upgrade(int oldVersion, int newVersion) throws SQLException {
        //数据库升级操作
        if(oldVersion < 2){
            //增加字段ext
            getDao(SimpleData.class).executeRaw("ALTER TABLE'simpledata' ADD COLUMN ext TEXT DEFAULT 'default';");
        }
        return true;
    }

}

数据库操作方法

//获取数据库操作接口
BaseDao<SimpleData> dao = EasyDBHelper.get().dao(SimpleData.class);

//增加
int line = dao.add(new SimpleData(1,"信息1"));

//查询所有
List<SimpleData> list = dao.queryAll();

//多条件查询并排序
List<SimpleData> list = dao.query(WhereInfo.get().between("index",1,18).equal("group1",true).order("id", false));
 
//分页查询-每页5条
WhereInfo info = WhereInfo.get().limit(5);
List<SimpleData> list = dao.queryLimit(info);//第一页查询
list = dao.queryLimit(info);//第二页查询

//更新
dao.update(data)

//删除
dao.delete(data)

//条目统计
long num = dao.countOf(WhereInfo.get().equal("group1", true));

//是否存在
boolean isExist = dao.isExist(WhereInfo.get().equal("description","信息2"));

//清空表
int line = dao.clearTable();

//批处理-批量操作消耗性能最低
dao.callBatchTasks(new Callable<SimpleData>() {
    @Override
    public SimpleData call() throws Exception {
        List<SimpleData> list = dao.queryAll();
        for(SimpleData data : list){
            data.description += "_批处理";
            dao.update(data);
        }
        return null;
    }
});

//更新-采用事务方式,自动回滚
dao.callInTransaction(new Callable<SimpleData>() {
    @Override
    public SimpleData call() throws Exception {
        List<SimpleData> list = dao.queryAll();
        if(!list.isEmpty()){
            SimpleData data = list.get(0);
            data.description = "更新内容";
            dao.update(data);
        }
        return null;
    }
});

//删除表
int clear = dao.dropTable();

/**
 * 异步任务方式一:在Activity/Fragment中尽量采用异步任务操作数据库
 * 异步任务可以重写run方法和onMainThread方法,可根据业务自定义重写方式
 **/
dao.asyncTask(new EasyRun<List<SimpleData>>(){
    //该方法在异步线程中执行
    @Override
    public List<SimpleData> run() throws Exception {
        return dao.queryAll();
    }
    //该方法在UI线程中执行
    @Override
    public void onMainThread(List<SimpleData> data) throws Exception {
        printList(data);
    }
});
//异步任务方式二
dao.asyncTask(new EasyRun<Object>(){
    @Override
    public Object run() throws Exception {
        return dao.queryAll();
    }

    @Override
    public void onMainThread(Object data) throws Exception {
        printList((List<SimpleData>)data);
    }
});
//异步任务方式三
dao.asyncTask(new EasyRun<SimpleData>(){
    @Override
    public SimpleData run() throws Exception {
        return dao.queryAll().get(0);
    }

    @Override
    public void onMainThread(SimpleData data) throws Exception {
        tvResult.setText(data.toString());
    }
});


数据库操作方法

public class SimpleData extends BaseModel {

    @DatabaseField(generatedId = true)
    public int id;
    @DatabaseField(index = true)
    public int index;
    @DatabaseField
    public String description;
    @DatabaseField
    public Date date;
    @DatabaseField
    public boolean group1;
    @DatabaseField
    public boolean group2;
    @DatabaseField
    public String ext;

    //必须有无参构造方法
    public SimpleData() {
    }

    public SimpleData(int index,String description) {
        this.date = new Date(System.currentTimeMillis());
        this.index = index;
        this.description = description;
        this.group1 = ((index % 2) == 0);
        this.group2 = ((index % 4) == 0);
        super.father = "基类"+index;
    }

}

数据库操作接口

package com.easydblib.dao;
import com.easydblib.callback.EasyRun;
import com.easydblib.info.WhereInfo;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.QueryBuilder;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * 数据库操作接口
 * @author : zhousf
 */
public interface BaseDao<T> {

    /**
     * 增加
     * @param model 映射类
     * @return 影响行数
     */
    int add(T model);

    /**
     * 增加集合
     * @param list 映射类集合
     * @return 影响行数
     */
    int add(List<T> list);

    /**
     * 增加或更新
     * @param model 映射类
     * @return 影响行数
     */
    int addOrUpdate(T model);

    /**
     * 不存在时增加
     * @param model 映射类
     * @return 增加的对象
     */
    T addIfNotExists(T model);

    /**
     * 删除
     * @param model 映射类
     * @return 影响行数
     */
    int delete(T model);

    /**
     * 删除集合
     * @param list 映射类集合
     * @return 影响行数
     */
    int delete(List<T> list);

    /**
     * 根据条件删除
     * @param whereInfo 查询信息体
     * @return 影响行数
     */
    int delete(WhereInfo whereInfo);

    /**
     * 更新
     * @param model 映射类
     * @return 影响行数
     */
    int update(T model);

    /**
     * 更新-根据查询条件进行更新,只更新第一条数据,若无则添加
     * @param model 映射类
     * @param whereInfo 查询信息体
     * @return 影响行数
     */
    int update(T model,WhereInfo whereInfo);

    /**
     * 查询所有
     * @return 映射类集合
     */
    List<T> queryAll();

    /**
     * 查询所有并排序
     * @param whereInfo 查询信息体
     * @return 映射类集合
     */
    List<T> queryAll(WhereInfo whereInfo);

    /**
     * 多条件查询并排序
     * @param whereInfo 查询信息体
     * @return 映射类集合
     */
    List<T> query(WhereInfo whereInfo);


    /**
     * 分页查询
     * @param whereInfo 查询信息体
     * @return 映射类集合
     */
    List<T> queryLimit(WhereInfo whereInfo);

    /**
     * 自定义查询
     * @param queryBuilder 查询构建
     * @return 映射类集合
     */
    List<T> query(QueryBuilder<T, Integer> queryBuilder);

    /**
     * 统计条目数
     * @return 条目数
     */
    long countOf();

    /**
     * 统计条目数
     * @param whereInfo 查询信息体
     * @return 条目数
     */
    long countOf(WhereInfo whereInfo);

    /**
     * 是否存在
     * @param whereInfo  查询信息体
     * @return true 存在  false 不存在
     */
    boolean isExist(WhereInfo whereInfo);

    /**
     * 执行原生的SQL语句
     * @param statement SQL语句
     * @param arguments 参数值-占位符?的值
     * @return 影响行数
     */
    int executeRaw(String statement, String... arguments);

    /**
     * 清空表
     * @return 条目数
     */
    int clearTable();

    /**
     * 删除表
     * @return 条目数
     */
    int dropTable();

    /**
     * 获取数据表DAO
     * @return dao
     */
    Dao<T, Integer> fetchDao();

    /**
     * 获取表名
     * @return 表名
     */
    String getTableName();

    /**
     * 执行事务
     * @param callable 事务回调
     */
    void callInTransaction(Callable<T> callable);

    /**
     * 批处理-大量数据库操作时请采用该方法(性能最优)
     * @param callable 回调
     */
    <CT> CT callBatchTasks(Callable<CT> callable);

    /**
     * 异步执行
     * @param easyRun 异步run
     */
    <T> void asyncTask(EasyRun<T> easyRun);

}

数据库操作代理类

package com.easydblib.handler;
import android.util.Log;
import com.easydblib.EasyDBConfig;
import com.easydblib.dao.RealBaseDao;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.table.TableUtils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * @author : zhousf
 * @description : 数据库操作代理类:主要进行预处理、日志打印
 * @date : 2017/5/23.
 */
public class EasyDBProxyHandler<T> implements InvocationHandler {

    private Object obj;
    private Dao<T, Integer> dao;
    private Class<T> mClass;
    private String databaseName;

    public EasyDBProxyHandler(Dao<T, Integer> dao, Class<T> mClass, String databaseName) {
        this.dao = dao;
        this.mClass = mClass;
        this.databaseName = databaseName;
    }

    public RealBaseDao<T> getProxy(Object targetObject) {
        this.obj = targetObject;
        Object proxy = Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(), this);
        return (RealBaseDao<T>)proxy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startTime = getTime();
        doBefore();
        Object result = method.invoke(obj, args);
        doAfter(method,result,startTime);
        return result;
    }

    /**
     * 执行前操作
     */
    private void doBefore(){
        prepareDeal();
    }

    /**
     * 执行后操作
     */
    private void doAfter(Method method, Object result, long startTime){
        if(result != null){
            String methodName = method.getName();
            if(result instanceof Integer || result instanceof Long){
                String line = String.valueOf(result);
                doLog(methodName+"["+(getTime()-startTime)+"ms] 影响行数:"+line);
            }else if(result instanceof List){
                int line = ((List) result).size();
                doLog(methodName+"["+(getTime()-startTime)+"ms] 影响行数:"+line);
            }else if(result instanceof Boolean){
                String res = String.valueOf(result);
                doLog(methodName+"["+(getTime()-startTime)+"ms] :"+res);
            }else {
                doLog(methodName+"["+(getTime()-startTime)+"ms] ");
            }
        }
    }

    /**
     * 预处理
     */
    private void prepareDeal(){
        checkTable();
    }

    /**
     * 检查数据表
     */
    private void checkTable(){
        try {
            TableUtils.createTableIfNotExists(dao.getConnectionSource(),mClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private long getTime(){
        return System.currentTimeMillis();
    }

    /**
     * 打印日志
     */
    private void doLog(String msg){
        if(EasyDBConfig.showDBLog)
            Log.d(EasyDBConfig.logTAG,msg+" | "+mClass.getSimpleName()+" | "+databaseName);
    }
}

相关截图

基本操作界面

有问题反馈

在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流

  • QQ: 424427633
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,515评论 25 707
  • 需要原文的可以留下邮箱我给你发,这里的文章少了很多图,懒得网上粘啦 1数据库基础 1.1数据库定义 1)数据库(D...
    极简纯粹_阅读 7,401评论 0 46
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,600评论 18 139
  • 古代神话故事中,经常出现修炼成精的狐狸,它们可以变成人形,通常都化作绝色美女。 最为出名的便是《封神榜》中的苏妲己...
    石之画趣阅读 1,355评论 14 18
  • 你們是否也有那麽一個人 儘管你們很久都不聯繫 平常很少聊天 在每年的每個節日你都會收到他的紅包 時間要麽在凌晨 要...
    慕幸晨曦阅读 236评论 0 1