当前位置: 首页 > article >正文

在uni-app中使用SQLite实现离线下数据同步:从封装到实践

场景:

在移动应用开发中,确保应用在无网络连接时仍能正常运行并进行数据同步至关重要。

对于uni-app开发者而言,SQLite是理想的本地存储解决方案,支持结构化数据的存储和检索。本文将介绍如何在uni-app项目中使用SQLite实现离线数据同步,包括封装sqlite.js简化数据库操作、测试数据库连接,需要在真机或雷电模拟器上进行调试。不能用内嵌的web浏览器,因为封装的sqlite里面的plus是只识别安卓;

注意:为实现离线数据同步,不能依赖终端部署的JAR包,而是直接使用SQLite进行数据处理。

1、在你的uni-app项目中创建一个名为sqlite.js的文件,包含所有与SQLite数据库交互的方法

module.exports = {
    dbName: '444', // 数据库名称
    dbPath: '/storage/emulated/0/Pictures/444.db', // 数据库地址,推荐以下划线为开头   _doc/xxx.db 
	
	/**
	  * @Description: 创建数据库 或 有该数据库就打开
	  *  
	  *  
	  *  
	  */
	openSqlite() {
	    return new Promise((resolve, reject) => {
			// 打开数据库
			plus.sqlite.openDatabase({
			    name: this.dbName,
			    path: this.dbPath,
			    success(e) {
				    resolve(e); 
			    },
			    fail(e) {
				    reject(e); 
			    }
			})
	    })
	},
	/**
	  * @Description: 判断数据库是否打开  数据库打开了就返回 true,否则返回 false
	  *  
	  * @createTime:  
	  *  
	  */
    isOpen() {
		var open = plus.sqlite.isOpenDatabase({
		    name: this.dbName,  // 数据库名称
		    path: this.dbPath  // 数据库地址
		})
		return open;
    },
	/**
	  * @Description: 创建表(executeSql是执行增删改等操作的SQL语句)
	  *  
	  * @createTime:  
	  *  
	  */
    ExecuteSQL(sql) {
		return new Promise((resolve, reject) => {
		    plus.sqlite.executeSql({
				name: this.dbName,
				sql: sql,
				success(e) {
				    resolve(e);
				},
				fail(e) {
				    reject(e);
				}
		    })
		})
    },
	/**
	  * @Description: 查询表数据
	  *  
	  * @createTime: 2023-10-12 08:52:15
	  *  
	  */
	getTable(dbTable){
	  	return new Promise((resolve, reject) => {
			plus.sqlite.selectSql({
				name: this.dbName,
				sql: `SELECT * FROM ${dbTable}`,
				success(e) {
					resolve(e);
				},
				fail(e) {
					console.log(e)
					reject(e);
				}
			})
	  	})
	},
	/**
	  * @Description: 查询表数据
	  *  
	  * @createTime: 2023-10-12 08:52:15
	  *  
	  */
	getSelectData(sql){
	  	return new Promise((resolve, reject) => {
			plus.sqlite.selectSql({
				name: this.dbName,
				sql: sql,
				success(e) {
					resolve(e);
				},
				fail(e) {
					console.log(e)
					reject(e);
				}
			})
	  	})
	},
	/**
	  * @Description: 查询数据库所有表
	  *  
	  * @createTime: 2023-10-12 09:01:05
	  *  
	  */
	QueryAllTables(){
		return new Promise((resolve, reject) => {
			plus.sqlite.selectSql({
				name: this.dbName,
				sql: "SELECT * FROM sqlite_master WHERE type='table'",
				success(e) {
					resolve(e);
				},
				fail(e) {
					console.log(e)
					reject(e);
				}
			})
		})
	},
	/**
	  * @Description: 查询数据库下的所有表
	  *  
	  * @createTime: 2023-10-12 09:20:33
	  *  
	  */
	selectTableName(){
		return new Promise((resolve, reject) => {
			plus.sqlite.selectSql({
				name: this.dbName,
				sql: "select * FROM chat where type='table'",
				success(e) {
					resolve(e);
				},
				fail(e) {
					console.log(e)
					reject(e);
				}
			})
		})
	},
	/**
	  * @Description: 新增数据
	  *  
	  * 向表格里添加数据 sql:'INSERT INTO dbTable VALUES('x','x','x')'   对应新增
	  * 或者 sql:'INSERT INTO dbTable ('x','x','x') VALUES('x','x','x')'   具体新增
	  * 插入 INSERT INTO  、 dbTable 是表名、根据表头列名插入列值
	  * @createTime: 2023-10-12 10:21:32
	  *  
	  */
	//使用
	// let arr = [
	//     {id:121,dept_id: '100',dept_name: '你好呀'},
	// 	   {id:332,dept_id: '200',dept_name: '你好呀'},
	// ]
	// arr.map((item) => {
	//     let condition = "'id','dept_id','dept_name'"
	//     let data = `'${item.id}','${item.dept_id}','${item.dept_name}'`
	//     DB.insertTableData('表名',数据,字段).then((res) => {})
	// 	  .catch((error) => {
	// 	    console.log('失败', error)
	// 	  })
	// })
	insertTableData(dbTable, data, condition) {
	    // 判断有没有传参
	    if (dbTable !== undefined && data !== undefined) {
			// 判断传的参是否有值
			var bol = (JSON.stringify(data) == "{}");
			if (!bol) {
				if (condition == undefined) var sql = `INSERT INTO ${dbTable} VALUES('${data}')`;
				else var sql = `INSERT INTO ${dbTable} (${condition}) VALUES(${data})`;
			    return new Promise((resolve, reject) => {
					// 表格添加数据
					plus.sqlite.executeSql({
					  name: this.dbName,
					  sql: sql,
					  success(e) {
						resolve(e);
					  },
					  fail(e) {
						reject(e);
					  }
					})
			    })
			} else {
			  return new Promise((resolve, reject) => { reject("错误添加") })
			}
		} else {
			return new Promise((resolve, reject) => { reject("错误添加") })
	    }
	},
	/**
	  * @Description: 数据库建表
	  *  
	  * 数据库建表 sql:'CREATE TABLE IF NOT EXISTS dbTable("id" varchar(50),"name" TEXT) 
	  * 创建 CREATE TABLE IF NOT EXISTS 、 dbTable 是表名,不能用数字开头、括号里是表格的表头
	  * @createTime: 2023-10-12 09:26:44
	  *  
	  */
    // 使用
	// DB.createTable('bus_mzpy','"id" INTEGER PRIMARY KEY AUTOINCREMENT,"mzpy_name" TEXT ,"dept_id" INTEGER ,"dept_name" TEXT ,"mzpy_concent" TEXT')
    createTable(dbTable, data) {  
		return new Promise((resolve, reject) => {
		    // executeSql: 执行增删改等操作的SQL语句
		    plus.sqlite.executeSql({
				name: this.dbName,
				sql: `CREATE TABLE IF NOT EXISTS ${dbTable}(${data})`,
				success(e) {
				    resolve(e);
				},
				fail(e) {
				    reject(e);
				}
		    })
		})
    },
	/**
	  * @Description: 数据库删表 sql:'DROP TABLE dbTable'
	  *  
	  * @createTime: 2023-10-12 09:28:46
	  *  
	  */
    dropTable(dbTable) {
		return new Promise((resolve, reject) => {
		    plus.sqlite.executeSql({
				name: this.dbName,
				sql: `DROP TABLE ${dbTable}`,
				success(e) {
					resolve(e);
				},
				fail(e) {
					reject(e);
				}
		    })
		})
    },
	/**
	  * @Description: 根据条件向表里插入数据、更新或覆盖
	  *  
	  *  根据条件向表格里添加数据  有数据更新、无数据插入
	  * (建表时需要设置主键) 例如 --- "roomid" varchar(50) PRIMARY KEY
	  * @createTime: 2023-10-12 09:31:19
	  *    1,名字 ,id,name 
	  */
    insertOrReplaceData(dbTable, data, condition) {
		// 判断有没有传参
		if (dbTable !== undefined && data !== undefined) {
			if (condition == undefined) var sql = `INSERT OR REPLACE INTO ${dbTable} VALUES('${data}')`;
			else var sql = `INSERT OR REPLACE INTO ${dbTable} (${condition}) VALUES(${data})`;
			return new Promise((resolve, reject) => {
			    // 表格添加数据
			    plus.sqlite.executeSql({
					name: this.dbName,
					sql: sql,
					success(e) {
						resolve(e);
					},
					fail(e) {
						reject(e);
					}
			    })
		    })
		} else {
		    return new Promise((resolve, reject) => { reject("错误添加") })
		}
    },
	/**
	  * @Description: 表里查询数据
	  *  
	  * 查询获取数据库里的数据 sql:'SELECT * FROM dbTable WHERE lname = 'lvalue''
	  * 查询 SELECT * FROM 、 dbTable 是表名、 WHERE 查找条件 lname,lvalue 是查询条件的列名和列值
	  * @createTime: 2023-10-12 09:44:08
	  *  
	  */ 
    selectTableData(dbTable, lname, lvalue, cc, dd) {
		if (dbTable !== undefined) {
			let sql;
		    // 第一个是表单名称,后两个参数是列表名,用来检索
		    // 两个检索条件
		    if (lname !== undefined && cc !== undefined) sql=`SELECT * FROM ${dbTable} WHERE ${lname} = '${lvalue}' AND ${cc} = '${dd}'`;
			// 一个检索条件
		    if (lname !== undefined && cc == undefined) sql = `SELECT * FROM ${dbTable} WHERE ${lname} = '${lvalue}'`;
		    if (lname == undefined) sql = `SELECT * FROM ${dbTable}`;
		    return new Promise((resolve, reject) => {
				// 表格查询数据  执行查询的SQL语句
				plus.sqlite.selectSql({
				    name: this.dbName,
				    sql: sql,
				    success(e) {
					    resolve(e);
				    },
				    fail(e) {
					    reject(e);
				    }
				})
		    })
		} else {
		  return new Promise((resolve, reject) => { reject("错误查询") });
		}
    },
    /**
      * @Description: 表里删除数据
      *  
      * 删除表里的数据 sql:'DELETE FROM dbTable WHERE lname = 'lvalue''
      * 删除 DELETE FROM 、 dbTable 是表名、 WHERE 查找条件 lname,lvalue 是查询条件的列名和列值
      * @createTime: 2023-10-12 09:40:37
      *  
      */
    deleteTableData(dbTable, lname, lvalue, ww, ee) {
		if(dbTable !== undefined){
			let sql;
		    if(lname == undefined){
			    sql = `DELETE FROM ${dbTable}`;
		    }else{
				if (ww !== undefined) {
				  // 两个检索条件
				  sql = `DELETE FROM ${dbTable} WHERE ${lname} = '${lvalue}' AND ${ww} = '${ee}'`;
				} else {
				  // 一个检索条件
				  sql = `DELETE FROM ${dbTable} WHERE ${lname} = '${lvalue}'`;
				}
		    }
			return new Promise((resolve, reject) => {
				// 删除表数据
				plus.sqlite.executeSql({
					name: this.dbName,
					sql: sql,
					success(e) {
						resolve(e);
					},
					fail(e) {
						reject(e);
					}
				})
			})
		} else {
		  return new Promise((resolve, reject) => { reject("错误删除") });
		}
    },
    /**
      * @Description: 表里修改数据
      *  
      * 修改数据表里的数据 sql:"UPDATE dbTable SET 列名 = '列值',列名 = '列值' WHERE lname = 'lvalue'"
      * 修改 UPDATE 、 dbTable 是表名, data: 要修改的列名=修改后列值, lname,lvalue 是查询条件的列名和列值
      * @createTime: 2023-10-12 09:37:59
      *  
      */
    updateTableData(dbTable, data, lname, lvalue) {
		let sql;
		if (lname == undefined) sql = `UPDATE ${dbTable} SET ${data}`;
		else sql = `UPDATE ${dbTable} SET ${data} WHERE ${lname} = '${lvalue}'`;
		// WHERE 前面是要修改的列名、列值,后面是条件的列名、列值
		return new Promise((resolve, reject) => {
		  // 修改表数据
		    plus.sqlite.executeSql({
				name: this.dbName,
				sql: sql,
				success(e) {
				  resolve(e);
				},
				fail(e) {
				  reject(e);
				}
		    })
		})
    },
	/**
	  * @Description: 获取指定数据条数
	  *  
	  * 获取指定数据条数  sql:"SELECT * FROM dbTable ORDER BY 'id' DESC LIMIT 15 OFFSET 'num'"
	  * dbTable 表名, ORDER BY 代表排序默认正序, id 是排序的条件 DESC 代表倒序,从最后一条数据开始拿
	  * LIMIT 15 OFFSET '${num}',这句的意思是跳过 num 条拿 15 条数据, num 为跳过多少条数据是动态值
	  * 例 初始num设为0,就从最后的数据开始拿15条,下次不拿刚获取的数据,所以可以让num为15,这样就能一步一步的拿完所有的数据
	  * @createTime: 2023-10-12 09:33:43
	  *  
	  */
	pullSQL(dbTable, id, num) {
		return new Promise((resolve, reject) => {
		    plus.sqlite.selectSql({
				name: this.dbName,
				sql: `SELECT * FROM ${dbTable} ORDER BY '${id}' DESC LIMIT 15 OFFSET '${num}'`,
				success(e) {
				  resolve(e);
				},
				fail(e) {
				  reject(e);
				}
		    })
		})
    },
    /**
    	* @Description: 关闭数据库
    	*  
    	* @createTime: 2023-10-12 09:23:56
    	*  
    	*/
    closeSqlite() {
		return new Promise((resolve, reject) => {
			plus.sqlite.closeDatabase({
				name: this.dbName,
				success(e) {
					resolve(e);
				},
				fail(e) {
					reject(e);
				}
			})
		})
    },
}

2、测试数据库是否成功打开

	import DB from '@/sqlite/sqlite.js'  //引入
   		//创建数据库 
		     DB.openSqlite()  
			// // //测试保存
         console.log("是否打开数据库" + DB.isOpen())

			// // 类似这样
			 DB.getTable('jc_repair_historical_record').then((res) => {
							 console.log('11111111db文件', res)

			}).catch((error) => {
			 	console.log('查询失败', error)
			 })
		 
			 //关闭数据库
		    DB.closeSqlite()

3、在真机或雷电模拟器上测试

由于plus相关的API仅能在真机或类似安卓手机的雷电模拟器上运行,因此这是验证SQLite数据库操作的最佳环境。请确保你已准备好相应的设备或模拟器,并按照上述步骤进行测试。

最后感谢阅读,如有不足指出,请指正,谢谢。


http://www.kler.cn/a/579378.html

相关文章:

  • 框架基本知识总结 Day15
  • 字母异位词分组 力扣49
  • UI自动化测试Selenium安装教程(1)
  • 解决VScode 连接不上问题
  • Python Flask 使用不同的 HTTP 方法类型处理请求
  • 华为OD机试-数组去重和排序(Java 2024 C卷 100分)
  • React 项目中 SVG 图标的调试和预览方法
  • Go红队开发—格式导出
  • 2025年最值得尝试的 8 个 AI 开源大模型
  • 嵌入式工控机在汽车制造中的卓越表现
  • Taro React组件开发 —— RuiNoticeBar 通知栏
  • 视觉图像处理
  • 读取 Resource 目录下文件内容
  • deepseek 3FS编译
  • TCP协议与包头格式
  • [HTTP协议]应用层协议HTTP从入门到深刻理解并落地部署自己的云服务(1)知识基础
  • 用Deepseek写一个 HTML 和 JavaScript 实现一个简单的飞机游戏
  • Java后端高频面经——JVM、Linux、Git、Docker
  • GPT 4.5 可能是戳破 AI 泡沫的模型
  • 力扣 最长公共子序列