首页 > 数据库 >electron 本地数据库sqlite

electron 本地数据库sqlite

时间:2023-10-16 11:22:37浏览次数:50  
标签:sqlite const name err 数据库 db electron params data

背景

某些不会频繁变动,但是数据量可能比较大,查询也比较频繁地数据,例如通讯录等。如果每次都查询服务器的数据库可能造成服务器压力过大,考虑在本地做数据库存储,有更新时从服务器同步数据到本地数据库,用户操作查询则使用本地数据库查询。

方案

  1. 进入页面时(或者其他适当时机)请求服务器数据,并将数据写入本地数据库。使用sqlite工具,通过sql语句建表,插入等方式。
    待解决的问题:json格式的数据如何通过sql语句批量插入数据库

  2. 有数据更新的时候同步触发本地数据库更新

  3. 查询时连接本地数据,进行查询

代码

安装sqlite

npm i sqlite3 --save-dev
npm install -g node-gyp
  1. 新建sqlite.ts文件,编写sqlite的工具函数
import sqlite3 from 'sqlite3';
const sqlite = sqlite3.verbose();

class Sqlite {
  constructor() {
    this.instance;
    this.db = null;
  }
  // 连接数据库
  connect(path) {
    return new Promise((resolve, reject) => {
      this.db = new sqlite.Database(path, err => {
        if (err === null) {
          resolve(err);
        } else {
          reject(err);
        }
      });
    });
  }
  // 运行sql
  run(sql, params) {
    return new Promise((resolve, reject) => {
      this.db.run(sql, params, err => {
        if (err === null) {
          resolve(err);
        } else {
          reject(err);
        }
      });
    });
  }
  // 运行多条sql
  exec(sql) {
    return new Promise((resolve, reject) => {
      this.db.exec(sql, err => {
        if (err === null) {
          resolve(err);
        } else {
          reject(err);
        }
      });
    });
  }
  // 查询一条数据
  get(sql, params) {
    return new Promise((resolve, reject) => {
      this.db.get(sql, params, (err, data) => {
        if (err) {
          reject(err);
        } else {
          resolve(data);
        }
      });
    });
  }
  // 查询所有数据
  all(sql, params) {
    return new Promise((resolve, reject) => {
      this.db.all(sql, params, (err, data) => {
        if (err) {
          reject(err);
        } else {
          resolve(data);
        }
      });
    });
  }
  // 关闭数据库
  close() {
    this.db.close();
  }

  //-----------SQL的一些方法封装---------------
  /**
   * 建表
   * @param tableName
   * @param columns
   */
  createTable(tableName, columns) {
    const columnDefinitions = columns.map(column => `${column.name} ${column.type}`).join(', ');
    const query = `CREATE TABLE IF NOT EXISTS ${tableName} (${columnDefinitions})`;
    this.db.run(query);
  }
  /**
   * 批量插入
   * @param tableName
   * @param data
   */
  insertData(tableName, data) {
    const columns = Object.keys(data).join(', ');
    const placeholders = Object.keys(data)
      .map(() => '?')
      .join(', ');
    const values = Object.values(data);
    const query = `INSERT OR IGNORE INTO ${tableName} (${columns}) VALUES (${placeholders})`;
    this.db.run(query, values);
  }
  updateData(tableName, data, condition) {
    const setClause = Object.keys(data)
      .map(column => `${column} = ?`)
      .join(', ');
    const values = Object.values(data);
    const query = `UPDATE ${tableName} SET ${setClause} WHERE ${condition}`;
    this.db.run(query, values);
  }

  deleteData(tableName, condition) {
    const query = `DELETE FROM ${tableName} WHERE ${condition}`;
    this.db.run(query);
  }
  /**
   * 多参数查询
   * @param params 
   * @returns 
   */
  executeQuery(params) {
    // todo: 后续拓展为可精准查询,可模糊查询
    const paramsStr = Object.keys(params)
    .filter(item=> !!params[item])
    .map(item=>{
      return params[item]?`${item} LIKE '%${params[item]}%'`:''
    })?.join(' AND ')
    const sql = `SELECT * FROM address_book ${paramsStr?`WHERE ${paramsStr}`:''}`
    console.log(sql)
    return new Promise((resolve, reject) => {
      this.db.all(sql, (err, rows) => {
        if (err) {
          console.error(err);
          reject(err)
        } else {
          resolve(rows)
        }
      });
    })
  }

  /**
   * 获取分页数据
   * @param tableName
   * @param page
   * @param pageSize
   * @param condition // const condition = "column_name = 'value'";
   * @returns {Promise<unknown>}
   */
  getPagedData(tableName, page, pageSize, condition) {
    const offset = (page - 1) * pageSize;
    const countQuery = `SELECT COUNT(*) as total FROM ${tableName} WHERE ${condition}`;
    const dataQuery = `SELECT * FROM ${tableName} WHERE ${condition} LIMIT ? OFFSET ?`;

    return new Promise((resolve, reject) => {
      this.db.serialize(() => {
        this.db.get(countQuery, (err, row) => {
          if (err) {
            reject(err);
          } else {
            const total = row.total;

            this.db.all(dataQuery, [pageSize, offset], (err, rows) => {
              if (err) {
                reject(err);
              } else {
                const totalPages = Math.ceil(total / pageSize);
                resolve({ data: rows, total, totalPages });
              }
            });
          }
        });
      });
    });
  }

 
  // 单例
  static getInstance() {
    this.instance = this.instance ? this.instance : new Sqlite();
    return this.instance;
  }
}

export default Sqlite;

  1. 新建sqliteUse.ts,使用sqlite
import Sqlite from './sqlite'
import { ipcMain } from 'electron';
import { join } from 'path';
const db = Sqlite.getInstance()
export const init = async() =>{
  // 这里前面还会有个生成.db文件的步骤,此处省略
    const dbPath = join(__dirname, './database.db')
    await db.connect(dbPath)

    // 新建通讯录的表
    const columns = [
      { name: 'id', type: 'INTEGER PRIMARY KEY AUTOINCREMENT' },
      { name: 'name', type: 'TEXT' },
      { name: 'mobile', type: 'INTEGER' },
      { name: 'phone', type: 'INTEGER' },
      { name: 'address', type: 'TEXT' },
      { name: 'company', type: 'TEXT' }
    ];
    db.createTable('address_book', columns);

    // 插入数据: 这个最终以服务器接口返回的为准,这里mock数据
    const data = [
      {
        id:1,
        name:'周杰伦',
        mobile:'18556781234',
        phone:'',
        address:'湖南省 长沙市 望城区 罐子岭1号',
        company:''
      },
      {
        id:2,
        name:'蔡依林',
        mobile:'18556781236',
        phone:'',
        address:'湖南省 长沙市 望城区 罐子岭2号',
        company:''
      },
    ]
    data.map(item=>{
      db.insertData('address_book', item);
    })
  
    // 监听数据库事件
    ipcMain.handle('sqlite-query',(event,params)=>{
      console.log(params)
      return new Promise<void>(async(resolve, reject) => {
        const res =  await db.executeQuery(params)
        resolve(res)
      })
    })
}


 //================= 使用案例 ==================================
 
  // // 执行自定义SQL查询
  // const query = 'SELECT * FROM users WHERE age > ?';
  // const params = [30];
  // const res = await db.executeQuery(query, params);
  //
  // // 创建表
  // const columns = [
  //   { name: 'id', type: 'INTEGER PRIMARY KEY AUTOINCREMENT' },
  //   { name: 'name', type: 'TEXT' },
  //   { name: 'age', type: 'INTEGER' }
  // ];
  // db.createTable('users', columns);
  //
  // // 插入数据
  // const data = { name: 'John Doe', age: 25 };
  // db.insertData('users', data);
  //
  // // 更新数据
  // const newData = { age: 30 };
  // const condition = 'name = "John Doe"';
  // db.updateData('users', newData, condition);
  //
  // // 删除数据
  // const deleteCondition = 'age > 30';
  // db.deleteData('users', deleteCondition);
  //
  // // 关闭数据库连接
  // db.close();

  //===================== 分页案例 ===============================
  // const page = 1;
  // const pageSize = 10;
  // const condition = "column_name = 'value'";
  // db.getPagedData("user", page, pageSize,condition)
  // .then(({ data, total, totalPages }) => {
  //   console.log(data); // 处理分页查询结果
  //   console.log(total); // 总数
  //   console.log(totalPages); // 总页数
  // })
  // .catch(err => {
  //   console.error(err); // 处理错误
  // })
  // .finally(() => {
  //   db.close(); // 关闭数据库连接
  // });
  //}
  1. 搜索列表demo:vue3 + antd
<template>
  <div class="list-container">
    <a-form
      layout="inline"
      :model="formState"
      @finish="handleFinish"
      @finishFailed="handleFinishFailed"
    >
      <a-form-item label="姓名">
        <a-input
          v-model:value="formState.name"
          placeholder="姓名"
        >
        </a-input>
      </a-form-item>
      <a-form-item label="手机号">
        <a-input
          v-model:value="formState.mobile"
          placeholder="手机号"
        >
        </a-input>
      </a-form-item>
      <a-form-item>
        <a-button
          type="primary"
          html-type="submit"
          @click="queryData"
        >
          查询
        </a-button>
      </a-form-item>
    </a-form>
    <a-table
      :dataSource="dbData"
      :columns="columns"
    />
  </div>
</template>
<script lang="ts">
import {defineComponent, ref,toRaw} from 'vue';
import {reactive} from 'vue';
import type {UnwrapRef} from 'vue';
import type {FormProps} from 'ant-design-vue';
export default defineComponent({
  // components: {
  //   Icon,
  // },
  setup() {
    const dbData = ref();

    interface FormState {
      name: string;
      mobile: string;
    }
    const formState: UnwrapRef<FormState> = reactive({
      name: '',
      mobile: '',
    });
    const handleFinish: FormProps['onFinish'] = values => {
      console.log(values, formState);
    };
    const handleFinishFailed: FormProps['onFinishFailed'] = errors => {
      console.log(errors);
    };
    async function queryData() {
      try {
        const params = toRaw(formState) 
        dbData.value = await window.electron.ipcRenderer.invoke('sqlite-query', params);
        console.log(dbData.value);
      } catch (error) {
        console.error(error);
      }
    }
    return {
      queryData,
      dbData,
      formState,
      handleFinish,
      handleFinishFailed,
      columns: [
        {
          title: '姓名',
          dataIndex: 'name',
          key: 'name',
        },
        {
          title: '手机号',
          dataIndex: 'mobile',
          key: 'mobile',
        },
        {
          title: '住址',
          dataIndex: 'address',
          key: 'address',
        },
      ],
    };
  },
});
</script>

效果预览

标签:sqlite,const,name,err,数据库,db,electron,params,data
From: https://www.cnblogs.com/lw5116/p/17766944.html

相关文章

  • 常用JDBC数据库驱动包和类名
    MySQL数据库:  1)驱动包:https://mvnrepository.com/artifact/mysql/mysql-connector-java(下载路径)  2)驱动类名:com.mysql.jdbc.Driver  3)JDBC的URL:jdbc:mysql://IP地址:端口号/数据库名字   注:端口号缺省为:3306    SQLserver数据库:  1)驱动包:https......
  • WINCCV7.5SP2无法安装SQL数据库的解决
    这一篇学习笔记我在新浪博客记录过,地址是WINCCV7.5SP2无法安装SQL数据库的解决_来自金沙江的小鱼_新浪博客(sina.com.cn)在这里我再记录一遍。今天在办公室一台纯净安装的windows10电脑上安装wincc7.5sp2过程中,SQL安装阶段提醒无法安装,然后整个安装就结束了。WINCC7.5SP2安装......
  • SQL Server数据库多种方式查找重复记录
    示例:表stuinfo,有三个字段recno(自增),stuid,stuname 建该表的Sql语句如下: CREATETABLE[StuInfo]([recno][int]IDENTITY(1,1)NOTNULL,[stuid][varchar](10)COLLATEChinese_PRC_CI_ASNOTNULL,[stuname][varchar](10)COLLATEChinese_PRC_CI_ASNOTNULL)ON[PRIMAR......
  • 创建数据库及工作表
    1.创建数据库:  createdatabasedatabase数据库名;示例:创建课程学习数据库SCTcreatedatabaseSCT;2.创建Table:Createtable表名(列名数据类型[PrimarykeyPrimarykey|Unique[Notnull]);Primarykey:主键约束。每个表只能创建一个主键约......
  • 了解 MySQL 数据库的三大日志(redo log、undo log、binary log)
    前言MySQL中有以下几种日志,包括:redolog(重做日志)undolog(回滚日志)binarylog(二进制日志)errorlog(错误日志)slowquerylog(慢查询日志)generallog(一般查询日志)relaylog(中继日志)事务的特性:原子性(Atomicity):事务是最小的执行单位,不允许分割。事务的原子......
  • Ubuntu18.04下使用PHP7.2的连接sql server数据库
     一、简介SQLServer是由Microsoft开发和推广的关系数据库管理系统(DBMS),它最初是由Microsoft、Sybase和Ashton-Tate三家公司共同开发的,并于1988年推出了第一个OS/2版本。MicrosoftSQLServer近年来不断更新版本,1996年,Microsoft推出了SQLServer6.5版本;1998年,SQLServer7.0版本......
  • 【精品】使用druid 获取数据库表的信息
    Maven依赖<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifac......
  • strapi系列-常用操作记录(创建中间件,创建关系型数据库,数据去掉attributes那一层)
    创建全局中间件创建关系型的数据https://docs.strapi.io/dev-docs/api/rest/relations{"product_types":{"connect":[10]},"product_tags":{"connect":[7,3,4]},"name":"TEST","......
  • 如何理解关系型数据库的常见设计范式?
    关系型数据库的常见设计范式有第一范式、第二范式和第三范式,分别简称为1NF、2NF和3NF。第一范式(1NF)是指一个关系(表)中的每个属性(列)都是不可分割的原子值。也就是说,如果一个属性可以被分成更小的子属性,那么它就不符合第一范式。例如,一个包含“姓名”和“地址”两个属性的表不符合第一......
  • Oracle数据库
    Ⅰ数据库①层次型数据库②网状型数据库③关系型数据库(主要介绍)E-R图:属性(椭圆形),实体(矩形),联系(菱形-一对一、一对多、多对多)注:有的联系也有属性关系型数据库的设计范式:第一范式(1NF):属性不可再分,字段保证原子性第二范式(2NF):在满足1NF的基础上,要求表中的每条记......