webDatabase封装类,方便不懂sql的前端人员使用

        近日,因webapp项目需要,需要使用websql来进行数据存储,但是websql直接使用的话有一些繁琐,会产生大量的冗余代码,并且最为一个前端数据库,对不懂sql的纯前端人员来说不太友好,为了方便使用,我就对其进行了一个小封装,因为时间有限,没有做的太完美,但是使用是很方便的,有需要的朋友可以自行拿来使用。

        本文主要是为了给同事当做API来看,而且也有工作要做,所以就不多花时间详细讲解开发思路和过程了,直接说明一下该组件拥有的功能和使用方式。各个方法只讲解使用方法,参数的具体说明见源码,还有什么不懂的可以直接评论或者在私信里问我。

更新日志:

2019-03-11(v1.1):
        1、修正了deleteById方法的默认提示文本;
        2、增加了ext方法,调用该方法并确认后,可以为组件临时添加批量修改和批量删除的方法,方法名为update和delete。
 
2019-03-07(v1.0):
        第一版发布。

类名:WebDatabase

创建对象:

var db = new WebDatabase('demo_table','1.0','测试数据库',1 * 1024 * 1024);

创建表数据:

db.createTable('demo1','id,name');//参数对应的是表名和字段

插入单条数据

db.insert('demo1','id,name',[1,'张三']);//参数对应的是:表名,字段名 ,字段值

批量插入数据:

db.batchInsert('demo1','id,name',[[2,'李四'],[3,'王二'],[4,'铁柱']])//用法和插入单挑数据差不多,只是数据的值从一维数组变成了二维数组

修改数据:为了数据安全,修改数据只支持按照id修改,如果各位使用我的组件时有需要按照更多条件修改的话,可以参照后面的查询方法来自行修改即可,很简单。

db.updateById('demo1',{id:1,name:'张三的大儿子'});//参数对应的是:表名,修改后数据,key要和表中字段对应

删除数据:同理,只支持按照id删除。

db.deleteById('demo1',3);//参数对应的是:表名,id。我这里是用数字当id,所以传入的是数字,在使用字符串当id时注意要传入字符串

查询方法:查询方法支持很多查询条件,直接看代码吧

//查询demo1表所有数据
db.select('demo1','*',null,function(datas){console.log(datas)});

//查询demo1表所有数据,但是只看name字段
db.select('demo1','name',null,function(datas){console.log(datas)});

//查询demo1表所有数据,但是只看id、age、name字段
db.select('demo1','id,age,name',null,function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询id=1的数据,条件查询中可以看到eq_XX,like_XX等key,具体支持哪些,以及有什么用,可以在本文最后方的源码中的方法注释中查看
db.select('demo1','*',{eq_id:1},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询id=1并且name='张三'的数据
db.select('demo1','*',{eq_name:'张三',eq_id:1},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name包含字符串'三'的数据
db.select('demo1','*',{like_name:'三'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name不等于'张三'的数据
db.select('demo1','*',{not_name:'张三'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name等于'张三'或者等于'李四'的数据
db.select('demo1','*',{in_name:'张三;李四'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name不等于'张三'并且不等于'李四'的数据
db.select('demo1','*',{notIn_name:'张三;李四'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name值为null的数据,其实null_XX的用法来说,无论值填的是什么都无所谓
//因为根本不回去读取值,所以我这里填了true,大家可以填任何值,例如{null_name : 0}
db.select('demo1','*',{null_name:true},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name不等于null数据,同理值不一定要是true,可以是任何值
db.select('demo1','*',{notNull_name:true},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name不等于null数据,并且按照id字段排顺序
db.select('demo1','*',{notNull_name:true,order:'id'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name不等于null数据,并且按照id字段排顺序
db.select('demo1','*',{notNull_name:true,order:'id asc'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name不等于null数据,并且按照id字段排倒序
db.select('demo1','*',{notNull_name:true,order:'id desc'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询name不等于null数据,并且先按照id字段排倒序,再按照name字段排倒序
db.select('demo1','*',{notNull_name:true,order:'id desc,name desc'},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询第1页的数据,每页2条数据
db.select('demo1','*',{page:1,pageSize:2},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询第2页的数据,每页2条数据
db.select('demo1','*',{page:2,pageSize:2},function(datas){console.log(datas)});

//查询demo1表所有字段,但是只查询第2页的数据,每页5条数据
db.select('demo1','*',{page:2,pageSize:5},function(datas){console.log(datas)});

生成查询条件、排序、分页的sql:这个方法是本组件的一个主要方法,其实一般来讲组件的使用者是不会用到的,这个方法供是select调用的。但是考虑到可能使用者会需要自己写一些sql来执行,可以通过这个方法来很便捷的生成条件语句,所以还是把这个方法暴露出来了。这个方法只有一个参数,和查询方法里面的第三个参数(conditions)是一样的用法,具体说明见下方的源码。

扩展方法:

在2019年3月11日更新的v1.1版本中,增加了ext方法,调用该方法并同意后,会为组件临时增加update(批量修改)和delete(批量删除)方法,具体见源码。调用方法如下:

db.ext();

这里直接贴出源码,大家可以根据需要任意修改,但是转载的话请注明出处:

/**
 * websql数据库工具
 * @version 1.1, Freddy-xjn
 *
 * 升版日志:
 *  2019-03-11(v1.1):
 *      1、修正了deleteById方法的默认提示文本;
 *      2、增加了ext方法,调用该方法并确认后,可以为组件临时添加批量修改和批量删除的方法,方法名为update和delete。
 *
 *  2019-03-07(v1.0):
 *      第一版发布。
 *
 * @param databaseName {String} 数据库名
 * @param version {String} 数据库版本
 * @param explain {String} 数据库说明
 * @param size {Int} 数据库大小,以字节为单位,1M = 1 * 1024 * 1024
 */
var WebDatabase = function(databaseName,version,explain,size){
    //防止直接调用方法导致this指向window,且没产生对象
    if(!(this instanceof WebDatabase)){
        return new WebDatabase(databaseName,version,explain,size);
    }

    this.databaseName = databaseName;
    this.version = version;
    this.explain = explain;
    this.size = size;

    //打开数据库
    this.db = openDatabase(databaseName, version, explain, size);
};

WebDatabase.prototype = {
    /**
     * 创建表
     * @param tableName {String} 表名
     * @param columns {String} 字段,多个字段用逗号分隔,例如:"id unique, log"
     * @param success {Function} 成功时的回调函数
     */
    createTable :  function(tableName,columns,success){
        var db = this.db;

        //默认的成功回调方法
        if(typeof success != 'function'){
            success = function(){
                console.log('表[' + tableName + ']创建成功!');
            };
        }

        //执行语句
        db.transaction(function (tx) {
            tx.executeSql('CREATE TABLE IF NOT EXISTS ' + tableName + ' (' + columns + ')');
        },function(text){
            console.error(text);
        },success);
    },
    /**
     *
     * @param tableName {String} 表名
     * @param columns {String} 字段,多个字段用逗号分隔,例如:"id unique, log"
     * @param conditions{Object} 条件<br>
     *     key可以包含以下类型,其中的XX为字段名:<br>
     *     <ul>
     *         <li>eq_XX:等于</li>
     *         <li>like_XX:like</li>
     *         <li>not_XX:不等于</li>
     *         <li>in_XX:包含,value中的多个值用分号分隔,
     *              例如:in_name : '张三;李四' 等价于sql中的 name in('张三','李四')
     *              即“name字段中的值等于'张三'或者等于'李四'”</li>
     *         <li>notIn_XX:不包含,多个值同样用分号分隔,参照in_XX的写法</li>
     *         <li>null_XX:为null,该属性的值不会被取到,所以值直接给true即可</li>
     *         <li>notNull_XX:不为null,该属性的值不会被取到,所以值直接给true即可</li>
     *         <li>order:order是用于排序的属性,当有值时,值必须为order的格式<br>
     *             例如:“age”,“age asc”,“age desc”<br>
     *             也支持多字段排序,写法如:“age,name desc”,“age asc,name”
     *             </li>
     *         <li>page:页码,分页的时候用,必须和pageSize同时有值才能生效</li>
     *         <li>pageSize:每页显示条数,必须和pageSize同时有值才能生效</li>
     *     </ul>
     * @param callback {Function} 调用成功时的回调函数,查询结果会以参数的形式传入
     */
    select : function(tableName,columns,conditions,callback){
        var db = this.db;

        var sql = 'SELECT ' + columns + ' FROM ' + tableName;

        var whereOrderData = this.createWhereSql(conditions);
        sql += whereOrderData.sql;

        db.transaction(function (tx) {
            tx.executeSql(sql, whereOrderData.params, function (tx, results) {
                if(typeof callback == 'function'){
                    callback(results.rows);
                }
            }, null);
        },function(text){
            console.error(text);
        });
    },
    /**
     * 插入单条数据
     * @param tableName {String} 表名
     * @param columns {String} 字段,多个字段用逗号分隔,例如:"id unique, log"
     * @param params {Array} 和字段顺序对应的数据值
     * @param success {Function} 成功时的回调函数
     */
    insert : function(tableName,columns,params,success){
        var db = this.db;

        //默认的成功回调方法
        if(typeof success != 'function'){
            success = function(){
                console.log('成功往[' + tableName + ']表插入1条数据!');
            };
        }

        //根据字段数量,决定要拼接几个占位符
        var valueStr = '';
        for(var i in columns.split(',')){
            if(i > 0){
                valueStr += ',';
            }
            valueStr += '?'
        }

        db.transaction(function (tx) {
            tx.executeSql('INSERT INTO ' + tableName + ' (' + columns + ') VALUES (' + valueStr + ')', params);
        },function(text){
            console.error(text);
        },success);
    },
    /**
     * 批量插入单条数据
     * @param tableName {String} 表名
     * @param columns {String} 字段,多个字段用逗号分隔,例如:"id unique, log"
     * @param params {Array[Array]} 二维数组,每个子数组存放和字段顺序对应的数据值
     * @param success {Function} 成功时的回调函数
     */
    batchInsert : function(tableName,columns,params,success){
        var db = this.db;

        //根据字段数量,决定要拼接几个占位符
        var valueStr = '';
        for(var i in columns.split(',')){
            if(i > 0){
                valueStr += ',';
            }
            valueStr += '?'
        }

        var sql = 'INSERT INTO ' + tableName + ' (' + columns + ') VALUES (' + valueStr + ')';
            db.transaction(function (tx) {
                for(var i = 0 ; i < params.length ; i++){
                    tx.executeSql(sql, params[i]);
                }
            },function(text){
                console.error('批量往[' + tableName + ']表插入数据失败!' +
                    '报错code为:' + text.code + ',报错信息为:' + text.message);
            },success ? success : function(){
                console.log('成功往[' + tableName + ']表插入' + params.length + '条数据!');
            });
    },
    /**
     * 根据id修改数据
     * @param tableName {String} 表名
     * @param datas {Object} 数据集,必须包含id字段,数据的key需对应表中的column,value对应修改后的数据
     * @param success {Function} 成功时的回调函数
     */
    updateById : function(tableName,datas,success){
        var db = this.db;

        //默认的成功回调方法
        if(typeof success != 'function'){
            success = function(){
                console.log('数据修改语句执行成功!');
            };
        }

        //根据datas生成修改数据sql
        var params = [];
        var updateSql = '';
        for(var key in datas){
            if(updateSql){
                updateSql += ',';
            }
            updateSql += key + '=?';
            params.push(datas[key]);
        }
        params.push(datas.id);

        db.transaction(function (tx) {
            tx.executeSql('UPDATE ' + tableName + ' SET ' + updateSql + ' WHERE id=?', params);
        },function(text){
            console.error(text);
        },success);
    },
    /**
     * 根据id删除数据
     * @param tableName {String} 表名
     * @param id {?} 要删除的数据的id
     * @param success {Function} 成功时的回调函数
     */
    deleteById : function(tableName,id,success){
        var db = this.db;

        //默认的成功回调方法
        if(typeof success != 'function'){
            success = function(){
                console.log('删除语句执行成功!');
            };
        }

        db.transaction(function(tx) {
            tx.executeSql('DELETE FROM ' + tableName + ' WHERE id=?', [id]);
        },function(text){
            console.error(text);
        },success);
    },
    /**
     * 创建条件、排序、分页的sql
     * @param conditions{Object} 使用方法参照select方法
     * @returns {Object} 返回值包含两个key,分别是sql和params
     */
    createWhereSql : function(conditions){
        conditions = conditions || {};
        var sql = '';//生成的sql
        var params = [];//参数

        //循环读取所有字段
        for(var key in conditions){
            //如果进入了这里,就说明至少有一个字段,此时如果sql为空,则追加where语句
            if(!sql){
                sql += ' where 1=1 ';
            }

            if(key.indexOf('eq_') == 0){//等于
                sql += ' and ' + key.replace('eq_','') + ' = ? ';
                params.push(conditions[key]);

            }else if(key.indexOf('like_') == 0){//like
                sql += ' and ' + key.replace('like_','') + ' like "%' + conditions[key] + '%" ';

            }else if(key.indexOf('not_') == 0){//不等于
                sql += ' and ' + key.replace('not_','') + ' != ? ';
                params.push(conditions[key]);

            }else if(key.indexOf('in_') == 0){//包含
                var val = conditions[key];
                var values = val.split(';');
                var inSql = '';

                for(var i in values){
                    if(inSql){
                        inSql += ',';
                    }
                    inSql += '?';
                    params.push(values[i]);
                }

                sql += ' and ' + key.replace('in_','') + ' in(' + inSql + ') ';

            }else if(key.indexOf('notIn_') == 0){//不包含
                var val = conditions[key];
                var values = val.split(';');
                var inSql = '';

                for(var i in values){
                    if(inSql){
                        inSql += ',';
                    }
                    inSql += '?';
                    params.push(values[i]);
                }

                sql += ' and ' + key.replace('notIn_','') + ' not in(' + inSql + ') ';

            }else if(key.indexOf('null_') == 0){//为null
                sql += ' and ' + key.replace('null_','') + ' is null ';

            }else if(key.indexOf('notNull_') == 0){//不为null
                sql += ' and ' + key.replace('notNull_','') + ' is not null ';

            }
        }

        //生成排序语句
        var order = conditions.order;
        if(order){
            sql += ' order by ' + order + ' ';
        }

        //生成分页语句
        var pageIndex = conditions.page;//页码
        var pageSize = conditions.pageSize;//每页条数
        var start = (pageIndex - 1) * pageSize;
        if(pageIndex != null && pageSize != null){
            sql += ' limit ' + start + ',' + pageSize;
        }

        return {
            sql : sql,
            params : params
        };
    },
    /**
     * 扩展组件功能,调用该方法并确认后,可以为组件临时添加新的功能,例如:
     * update : 批量修改数据
     * delete : 批量删除数据
     */
    ext : function(){
        var flag = confirm('该操作将提供根据更多条件进行批量删除和批量修改数据的方法,' +
            '可能造成数据安全问题,是否确定扩展该方法?');
        if(flag){

            /**
             * 批量修改数据
             * @param tableName {String} 表名
             * @param datas {Object} 数据集,必须包含id字段,数据的key需对应表中的column,value对应修改后的数据
             * @param conditions conditions{Object} 使用方法参照select方法。
             *      注意!!!!如果未传入任何条件的话将对全表数据进行修改,慎用!!!!
             * @param success {Function} 成功时的回调函数
             */
            WebDatabase.prototype.update = function(tableName,datas,conditions,success){
                var db = this.db;

                //默认的成功回调方法
                if(typeof success != 'function'){
                    success = function(){
                        console.log('数据修改语句执行成功!');
                    };
                }

                //根据datas生成修改数据sql
                var params = [];
                var updateSql = '';
                for(var key in datas){
                    if(updateSql){
                        updateSql += ',';
                    }
                    updateSql += key + '=?';
                    params.push(datas[key]);
                }

                //生成条件语句
                var sql = 'UPDATE ' + tableName + ' SET ' + updateSql + ' ';
                var whereOrderData = this.createWhereSql(conditions);
                sql += whereOrderData.sql;

                //执行sql
                db.transaction(function (tx) {
                    tx.executeSql(sql, params.concat(whereOrderData.params));
                },function(text){
                    console.error(text);
                },success);

            };

            /**
             * 批量删除数据
             * @param tableName {String} 表名
             * @param conditions conditions{Object} 使用方法参照select方法。
             *      注意!!!!如果未传入任何条件的话将对全表数据进行删除,慎用!!!!
             * @param success {Function} 成功时的回调函数
             */
            WebDatabase.prototype.delete = function(tableName,conditions,success){
                var db = this.db;

                //默认的成功回调方法
                if(typeof success != 'function'){
                    success = function(){
                        console.log('删除语句执行成功!');
                    };
                }

                //生成条件语句
                var sql = 'DELETE FROM ' + tableName + ' ';
                var whereOrderData = this.createWhereSql(conditions);
                sql += whereOrderData.sql;

                db.transaction(function(tx) {
                    tx.executeSql(sql, whereOrderData.params);
                },function(text){
                    console.error(text);
                },success);
            };
        }
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值