【Android】GreenDao数据库的使用方式
需求
使用GreenDao数据库进行数据的存储。
介绍
GreenDao 是一个轻量级的对象关系映射(ORM)库,用于简化 Android 应用中的数据库操作。它提供了以下主要功能:
简化数据库操作:通过注解定义实体类,GreenDao 自动生成 DAO(数据访问对象)类,简化了数据库的增、删、改、查操作。
高性能:GreenDao 设计目标之一是高效地执行数据库操作,尤其在处理大量数据时表现出色。
自动生成代码:通过编译时生成代码,减少了手动编写 SQL 和数据处理逻辑的需要。
事务支持:支持数据库事务,确保数据操作的原子性和一致性。
灵活性:可以通过自定义查询和批量操作,满足复杂的数据处理需求。
小巧:库体积小,适合需要轻量级 ORM 的应用。
集成
在 build.gradle 文件中添加 GreenDao 依赖:
implementation 'org.greenrobot:greendao:3.3.0'
配置 build.gradle 以生成 DAO 类。添加插件和配置:
apply plugin: 'org.greenrobot.greendao'greendao {schemaVersion 1 //定义数据库的版本号,用于处理数据库升级。daoPackage 'com.example.dao' //指定生成的 DAO 类包名。targetGenDir 'src/main/java' //指定生成的实体类包名。
}
使用
创建实体类:
使用 GreenDao 提供的注解定义实体类。举例:
@Entity
public class UpdateBean{@Id(autoincrement = true)private Long id;private String name;// getters and setters
}
创建实体类之后,使用Build重新构建一下项目,然后会自动生成相关文件
【DaoMaster】【DaoSession】【UpdateBeanDao】
创建一个帮助类 【UpdateOpenHelper】
public class UpdateOpenHelper extends DaoMaster.OpenHelper {public UpdateOpenHelper(Context context, String name) {super(context, name);}public UpdateOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {super(context, name, factory);}@Overridepublic void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {DaoMaster.dropAllTables(wrap(db), true);}@Overridepublic void onUpgrade(Database db, int oldVersion, int newVersion) {super.onUpgrade(db, oldVersion, newVersion);}
}
创建一个管理类【UpdateManager 】
public class UpdateManager {private Context mContext;private static UpdateManager manager = new UpdateManager();private static ConcurrentHashMap<String, DaoMaster> masterMap = new ConcurrentHashMap<>();private static ConcurrentHashMap<String, DaoSession> daoSessionMap = new ConcurrentHashMap<>();private static ConcurrentHashMap<String, UpdateOpenHelper> helperMap = new ConcurrentHashMap<>();public static UpdateManager getInstance() {return manager;}public void init(Context context) {this.mContext = context;}private DaoMaster getDaoMaster(String dbName) {if (!masterMap.containsKey(dbName)) {UpdateOpenHelper openHelper = helperMap.get(dbName);if (openHelper == null) {UGDaoContext daoContext = new UGDaoContext(mContext);openHelper = new UpdateOpenHelper(daoContext, dbName, null);helperMap.put(dbName, openHelper);}DaoMaster master;try {master = new DaoMaster(openHelper.getWritableDatabase());masterMap.put(dbName, master);} catch (Exception e) {e.printStackTrace();}}return masterMap.get(dbName);}public DaoSession getDaoSession(String dbName) {if (!daoSessionMap.containsKey(dbName)) {DaoMaster master = getDaoMaster(dbName);if (master != null) {DaoSession session = master.newSession();daoSessionMap.put(dbName, session);}}return daoSessionMap.get(dbName);}/*** 关闭指定数据库连接** @param dbName 数据库名字*/public void closeConnection(String dbName) {DaoSession session = daoSessionMap.get(dbName);if (session != null) {session.clear();daoSessionMap.remove(dbName);}DaoMaster master = masterMap.get(dbName);if (master != null) {master = null;masterMap.remove(dbName);}UpdateOpenHelper helper = helperMap.get(dbName);if (helper != null) {helper.close();helperMap.remove(dbName);}}/*** 关闭所有数据库连接*/public void closeAllConnection() {// 关闭所有DaoSessionssynchronized (this) {for (String dbName : daoSessionMap.keySet()) {closeConnection(dbName); // 关闭每一个连接}// 额外步骤:清理所有映射daoSessionMap.clear();masterMap.clear();helperMap.clear();}}}
还有需要修改数据库的文件的存储路径,GreenDao数据库默认的存储路径是在应用内部私有存储,所以如果删除了应用之后,数据文件也会被删除,同时也不利于外部查找数据库文件。
创建【UGDaoContext】修改数据库文件地址
public class UGDaoContext extends ContextWrapper {public UGDaoContext(Context base) {super(base);}@Overridepublic File getDatabasePath(String name) {String dbDir;boolean isExistSDCar = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);if (isExistSDCar) {dbDir = Environment.getExternalStorageDirectory().getAbsolutePath();} else {dbDir = Environment.getDataDirectory().getAbsolutePath();}String dbDirPath = dbDir + File.separator + "app_dao" + File.separator + "data_update";Log.d("TAG", "数据库的文件夹地址:" + dbDirPath);File dbDirFile = new File(dbDirPath);if (!dbDirFile.exists()) {dbDirFile.mkdirs();}String dbNamePath = dbDirPath + File.separator + name;File dbNameFile = new File(dbNamePath);boolean isSuccess = false;if (!dbNameFile.exists()) {try {isSuccess = dbNameFile.createNewFile();} catch (IOException e) {e.printStackTrace();}} else {isSuccess = true;}if (isSuccess) {Log.d("TAG", "数据库的文件地址:" + dbNamePath);return dbNameFile;} else {return super.getDatabasePath(name);}}@Overridepublic SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);}@Overridepublic SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);}
}
接下里再创建一个工具类实现对数据库的操作【UpdateDaoUtil】
public class UpdateDaoUtil {private UpdateManager manager;public UpdateDaoUtil(Context context) {manager = UpdateManager.getInstance();manager.init(context);}/*** 完成UpdateBean记录的插入*/public synchronized boolean insertUpdate(UpdateBean updateBean, String dbName) {boolean flag = false;if (manager.getDaoSession(dbName).getUpdateBeanDao().insert(updateBean) != -1) {flag = true;}return flag;}/*** 完成UpdateBean记录的插入*/public synchronized boolean insertUpdate(UpdateBean updateBean) {boolean flag = false;if (manager.getDaoSession(getCurrentDBName()).getUpdateBeanDao().insert(updateBean) != -1) {flag = true;}return flag;}/*** 完成UpdateBean列表记录的插入*/public synchronized boolean insertUpdate(List<UpdateBean> list) {int frequency = 0;UpdateBeanDao dao = manager.getDaoSession(getCurrentDBName()).getUpdateBeanDao();for (UpdateBean updateBean : list) {if (dao.insert(updateBean) == -1) {frequency++;}}return frequency == 0;}/*** 删除单条记录*/public synchronized boolean deleteUpdateBean(UpdateBean updateBean, String dbName) {boolean flag = false;try {manager.getDaoSession(dbName).delete(updateBean);flag = true;} catch (Exception e) {e.printStackTrace();}return flag;}/*** 删除单条记录*/public synchronized boolean deleteUpdateBean(UpdateBean updateBean) {boolean flag = false;try {manager.getDaoSession(getCurrentDBName()).delete(updateBean);flag = true;} catch (Exception e) {e.printStackTrace();}return flag;}/*** 删除所有记录*/public synchronized boolean deleteAll(String dbname) {boolean flag = false;try {manager.getDaoSession(dbname).deleteAll(UpdateBean.class);flag = true;} catch (Exception e) {e.printStackTrace();}return flag;}/*** 删除所有记录*/public synchronized boolean deleteAll() {boolean flag = false;try {manager.getDaoSession(getCurrentDBName()).deleteAll(UpdateBean.class);flag = true;} catch (Exception e) {e.printStackTrace();}return flag;}/*** 查询数据库前 number 条数据*/public synchronized List<UpdateBean> queryDataNumber(int number, String dbname) {QueryBuilder<UpdateBean> queryBuilder = manager.getDaoSession(dbname).queryBuilder(UpdateBean.class);return queryBuilder.limit(number).list();}/*** 查询数据库前 number 条数据*/public synchronized List<UpdateBean> queryDataNumber(int number) {QueryBuilder<UpdateBean> queryBuilder = manager.getDaoSession(getCurrentDBName()).queryBuilder(UpdateBean.class);return queryBuilder.limit(number).list();}/*** 删除数据库前 number 条数据*/public synchronized void deleteDataNumber(int number, String dbname) {UpdateBeanDao dao = manager.getDaoSession(dbname).getUpdateBeanDao();List<UpdateBean> lists = dao.queryBuilder().limit(number).list();dao.deleteInTx(lists);}/*** 删除数据库前 number 条数据*/public synchronized void deleteDataNumber(int number) {UpdateBeanDao dao = manager.getDaoSession(getCurrentDBName()).getUpdateBeanDao();List<UpdateBean> lists = dao.queryBuilder().limit(number).list();dao.deleteInTx(lists);}/*** 查询所有记录*/public synchronized List<UpdateBean> queryAll(String dbName) {return manager.getDaoSession(dbName).loadAll(UpdateBean.class);}/*** 查询所有记录*/public synchronized List<UpdateBean> queryAll() {return manager.getDaoSession(getCurrentDBName()).loadAll(UpdateBean.class);}/*** 使用指定名称的数据库,每次查询200条未上传的数据** @param dbname 数据库表名称*/public synchronized List<UpdateBean> queryListUpdate(String dbname) {QueryBuilder<UpdateBean> queryBuilder = manager.getDaoSession(dbname).queryBuilder(UpdateBean.class);return queryBuilder.where(UpdateBeanDao.Properties.IsUpdate.eq(0)).limit(200).list();}/*** 更新是否上传状态** @param list 上传数据的ID的list*/public synchronized void updateStatus(List<Long> list) {DaoSession daoSession = manager.getDaoSession(getCurrentDBName());UpdateBeanDao updateBeanDao = daoSession.getUpdateBeanDao();try {daoSession.runInTx(() -> {for (Long id : list) {UpdateBean bean = updateBeanDao.load(id);if (bean != null) {bean.setIsUpdate(1);updateBeanDao.update(bean);}}});} catch (Exception e) {e.printStackTrace();}}/*** 更新是否上传状态** @param dbName 数据库表名字* @param list 上传数据的ID的list*/public synchronized void updateStatus(String dbName, List<Long> list) {DaoSession daoSession = manager.getDaoSession(dbName);UpdateBeanDao updateBeanDao = daoSession.getUpdateBeanDao();try {daoSession.runInTx(() -> {for (Long id : list) {UpdateBean bean = updateBeanDao.load(id);if (bean != null) {bean.setIsUpdate(1);updateBeanDao.update(bean);}}});} catch (Exception e) {e.printStackTrace();}}/*** 使用queryBuilder进行查询未上传的数据*/public synchronized List<UpdateBean> queryItemByQueryBuilder(int isUpdate) {QueryBuilder<UpdateBean> queryBuilder = manager.getDaoSession(getCurrentDBName()).queryBuilder(UpdateBean.class);return queryBuilder.where(UpdateBeanDao.Properties.IsUpdate.eq(isUpdate)).limit(100).list();}/*** 关闭当前日期资源*/public synchronized void close() {manager.closeConnection(getCurrentDBName());}/*** 关闭特定名字的数据资源*/public synchronized void close(String dbName) {manager.closeConnection(dbName);}/*** 关闭所有连接*/public synchronized void closeAll() {manager.closeAllConnection();}/*** 数据表的名称是当天的日期** @return 当天日期*/private static String getCurrentDateFormatted() {long currentTimeMillis = System.currentTimeMillis();Date date = new Date(currentTimeMillis);SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());return sdf.format(date);}/*** 获取当天数据库表的名称*/private static String getCurrentDBName() {return getCurrentDateFormatted() + "_db";}/*** 组装数据库名字** @param dateTime 日期时间 例如 20240814*/public static String setDBName(String dateTime) {return dateTime + "_db";}
}
这样基本上一个数据库就创建了,剩下就是如何使用了。
UpdateDaoUtil updateDaoUtil;
updateDaoUtil = new UpdateDaoUtil(this);
if (updateDaoUtil != null) {Log.i("TAG", "将List数据存入本地数据库,存入条数 " + updateBeanList.size());List<UpdateBean> list = new ArrayList<>(updateBeanList);boolean update = updateDaoUtil.insertUpdate(list);if (update) {Log.i("TAG", "数据存入数据库正常");}}
记得销毁
@Overrideprotected void onDestroy() {super.onDestroy();if (updateDaoUtil != null) {updateDaoUtil.closeAll();}}
GreenDao数据库的基本使用方式就是这样了。
相关文章:
【Android】GreenDao数据库的使用方式
需求 使用GreenDao数据库进行数据的存储。 介绍 GreenDao 是一个轻量级的对象关系映射(ORM)库,用于简化 Android 应用中的数据库操作。它提供了以下主要功能: 简化数据库操作:通过注解定义实体类,Green…...
搜索算法之线性搜索详细解读(附带Java代码解读)
1. 基本概念 线性搜索(Linear Search),也称为顺序搜索,是一种在列表中查找特定元素的算法。它从列表的第一个元素开始,逐个检查每个元素,直到找到目标元素或检查完所有元素。 2. 工作原理 线性搜索的操作…...
Quartz.Net_依赖注入
简述 有时会遇到需要在IJob实现类中依赖注入其他类或接口的情况,但Quartz的默认JobFactory并不能识别具有有参构造函数的IJob实现类,也就无法进行依赖注入 需要被依赖注入的类: public class TestClass {public TestClass(Type jobType, s…...
【系统架构设计师-2011年】综合知识-答案及详解
更多内容请见: 备考系统架构设计师-核心总结索引 文章目录 【第1题】【第2~4题】【第5~7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18~19题】【第20~21题】【第22题】【第23题】【第24题】【第25题】【第2…...
World of Warcraft [CLASSIC][80][Grandel]Sapphire Hive Drone
Sapphire Hive Drone 蓝玉虫巢雄蜂 蓝玉虫巢巨峰 索拉查盆地 实用性不强,好看是好看,模型很大,无奈栏位太少...
Unity 对接 Android 第三方广告,App 切换到后台后,再次打开时,第三方广告被销毁导致无法触发回调逻辑的问题
该问题是由发行进行游戏测试时遇到并反馈的。大致情况如下: 1. 当触发了插屏广告后,在关闭广告前将 App 切换到后台,之后再次打开 App,此时插屏广告消失,并切游戏卡死。 2. 当触发激励视频广告后,在广告展…...
Kafka Broker处于高负载状态(例如消息处理量大或系统资源不足),无法及时响应消费者的请求
Caused by: org.apache.kafka.common.errors.TimeoutException: Timeout of 60000ms expired before the position for partition activity-0 could be determined。 出现这个错误的原因是Kafka消费者在尝试获取分区(activity-0)的位置信息时,超时了。在60秒内无法确…...
相关二叉树进阶面试题的讲解?看这一篇足矣
引子:我们在之前学过c语言的二叉树,但是c来做更好!本期要讲的题目如下(其实有点拖欠了,很久之前,就想写这个了,今天终于克服自己的欲望,达成了这个愿望) 1, 二叉树创建字…...
Nginx部署前端Vue项目的深度解析
目录 一、准备工作 1.1 开发环境 1.2 服务器环境 1.3 Nginx安装 二、构建Vue项目 三、上传静态文件到服务器 四、配置Nginx 五、测试并重新加载Nginx 六、访问Vue应用 七、高级配置 7.1 启用HTTPS 7.2 启用Gzip压缩 7.3 缓存控制 八、常见问题与解决方案 8.1 40…...
PHP一站式解决方案高级房产系统小程序源码
一站式解决方案,高级房产系统让房产管理更轻松 🏠【开篇:告别繁琐,迎接高效房产管理新时代】🏠 你是否还在为房产管理的繁琐流程而头疼?从房源录入、客户咨询到合同签订、售后服务,每一个环节…...
轻量级模型解读——EfficientNet系列
EfficientNet自2019年谷歌提出以来,经历了三个版本,2019EfficientNet ——> 2020EfficientNet-Lite——> 2021EfficientNetv2 文章目录 1、EfficientNet2、EfficientNetv23、EfficientNet-Lite 对于EfficientNet和EfficientNetv2的解读可见另外两篇…...
深入浅出SRS—RTMP实现
RTMP 直播是 SRS 最典型的使用场景,客户端使用 RTMP 协议向 SRS 推流,使用 RTMP 协议从 SRS 拉流,SRS 作为一个 RTMP 直播服务器实现媒体的转发。同时,RTMP 是 SRS 的中转协议,其他协议之间的互通需要先转为 RTMP&…...
睿赛德科技携手先楫共创RISC-V生态|RT-Thread EtherCAT主从站方案大放异彩
日前,在先楫HPM6E00技术日上,睿赛德科技(RT-Thread)向广大工业用户展示了多年来双方在RISC-V生态领域的合作历程和成果,同时睿赛德科技携手先楫半导体首次推出了基于HPM6800处理器的EtherCAT主站解决方案,吸…...
【Cesium实体创建】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Cesium目录 前言一、Cesium二、点 线 实体1.点实体2.线实体 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不…...
为何一些包的Priority在apt-cache和deb文件当中的不一样
最近遇到一些问题,调查的时候发现是一些包的Priority在apt-cache和deb文件当中的不一样导致的,复现步骤如下: $ apt update $ apt download whiptail $ dpkg-deb -e whiptail_0.52.23-1b1_amd64.deb $ cat control | grep Prio Priority: op…...
CRUD的最佳实践,联动前后端,包含微信小程序,API,HTML等(三)
关说不练假把式,在上一,二篇中介绍了我心目中的CRUD的样子 基于之前的理念,我开发了一个命名为PasteTemplate的项目,这个项目呢后续会转化成项目模板,转化成项目模板后,后续需要开发新的项目就可以基于这…...
nvidia-cuda-tensorrt-cudnn下载网站
tensorrt:https://developer.nvidia.com/tensorrt/download cudnn:https://developer.nvidia.com/rdp/cudnn-archive cuda:https://developer.nvidia.com/cuda-toolkit-archive...
GitLab 是什么?GitLab使用常见问题解答
GitLab 是什么 GitLab是由GitLab Inc.开发,使用MIT许可证的基于网络的Git仓库管理工具开源项目,且具有wiki和issue跟踪功能,使用Git作为代码管理工具,并在此基础上搭建起来的web服务。 GitLab 是由 GitLab Inc.开发,…...
数字时代,寻找新的生意增长点之前要做什么准备?
要做好最基础也最繁复的数据管理。 在竞争日益激烈的快消市场中,企业面临前所未有的挑战与压力。在这种高压环境下,数字化转型不再仅仅是选择,而是企业探索新的业务增长点、保持竞争优势的关键战略。然而,随着企业数字化进程的加…...
使用Python本地搭建http.server文件共享服务并实现公网环境远程访问——“cpolar内网穿透”
前言 本文主要介绍如何在Windows系统电脑上使用python这样的简单程序语言,在自己的电脑上搭建一个共享文件服务器,并通过cpolar创建的公网地址,打造一个可以随时随地远程访问的私人云盘。 数据共享作为和连接作为互联网的基础应用ÿ…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...
