【问题标题】:Ionic Prepopulated Database with Antair Cordova SQLitePlugin [help request]使用 Antair Cordova SQLitePlugin 的离子预填充数据库 [帮助请求]
【发布时间】:2015-01-30 00:22:36
【问题描述】:

____ 简介

大家好,首先澄清三点:

  1. 我的英语不好,所以我的错误请提前见谅,
  2. 我是新手,请原谅我的不准确之处,
  3. 我之前搜索并尝试了我在互联网上找到的解决方案,但仍然无法解决嵌入预填充数据库的问题。

____ 目标

我想使用预填充数据库开发适用于 iOS 和 Android 的应用。

例如,数据库由 15.000 条记录组成,每条记录由三个键值对(idfirstname姓氏)。

___ 我做了什么

步骤:

ionic start myapp blank
cd myapp
ionic platform add ios
ionic platform add android

然后我创建了一个用于测试目的的 sqlite 数据库,名为 mydb.sqlite,由一个表 people 组成,其中包含两个 idfirstnamelastname 记录。

我决定使用以下插件:https://github.com/Antair/Cordova-SQLitePlugin 那是因为它可以用cordova工具安装。

ionic plugin add https://github.com/Antair/Cordova-SQLitePlugin

警告:我认为网站上的说明显示不正确的引用 - “cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin - 指的是另一个插件)。

然后,按照插件网站上的说明,我将数据库复制到 myapp/www/db/,以便现在可以在 myapp/www/db/mydb 中找到它。 sqlite

我在默认 app.js 脚本之后修改了 index.html,包括 SQLite 插件:

<!-- your app's js -->
<script src="js/app.js"></script>
<script src="SQLitePlugin.js"></script>

我还在 index.html 文件中写了几行代码来显示一个按钮:

<ion-content ng-controller="MyCtrl">
    <button class="button" ng-click="all()">All</button>
</ion-content>

最后我修改了./js/app.js

// Ionic Starter App

var db = null;

angular.module('starter', ['ionic' /* What goes here? */ ])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // some predefined code has been omitted

    window.sqlitePlugin.importPrepopulatedDatabase({file: "mydb.sqlite", "importIfExists": true});
    db = window.sqlitePlugin.openDatabase({name: "mydb.sqlite"});

  }); // $ionicPlatform.ready
}) // .run

.controller('MyCtrl', function($scope){

    $scope.all = function(){
            var query = "SELECT * FROM people";
            // I don't know how to proceed

    }; // $scope.all

}); // .controller

___ 问题

我不知道如何在控制器部分继续查询所有记录(只是一个查询示例)并在 console.log 中显示结果。

我认为以下代码必须以某种方式完成:

angular.module('starter', ['ionic' /* What goes here? */ ]) 

控制器部分内的代码也必须完成:

       $scope.all = function(){
                var query = "SELECT * FROM people";
                // I don't know how to proceed

        }; // $scope.all

___ 最后的感谢

提前感谢您对我的帮助。

【问题讨论】:

    标签: ios sqlite cordova ionic


    【解决方案1】:

    所以这个家伙的代码对封装我的 DAL 有很大帮助。我强烈建议您逐字使用他的代码。

    https://gist.github.com/jgoux/10738978

    你会看到他有以下方法:

    self.query = function(query, bindings) {
        bindings = typeof bindings !== 'undefined' ? bindings : [];
        var deferred = $q.defer();
    
        self.db.transaction(function(transaction) {
            transaction.executeSql(query, bindings, function(transaction, result) {
                deferred.resolve(result);
            }, function(transaction, error) {
                deferred.reject(error);
            });
        });
    
        return deferred.promise;
    };
    

    让我们稍微分解一下。查询函数接受一个查询字符串(查询参数)和一个可能的绑定列表?在类似“SELECT * FROM A_TABLE WHERE ID = ?”的查询中。因为他的代码是服务,所以 self 值指向服务本身以供将来所有调用使用。该函数将对 db 执行事务,但它返回一个仅在 db 恢复后才会履行的承诺。

    他的服务提供了第二个辅助函数:fetchAll。

    self.fetchAll = function(result) {
        var output = [];
    
        for (var i = 0; i < result.rows.length; i++) {
            output.push(result.rows.item(i));
        }
    
        return output;
    };
    

    fetchAll 将整个行读入一个数组。 fetchAll 的结果参数是在查询函数的承诺履行中传递的结果变量。

    如果您将他的代码复制并粘贴到您的服务文件中,您现在就拥有了一个真正的数据库服务。您可以将该服务包装在 DAL 中。这是我项目中的一个示例。

    .service('LocationService', function ($q, DB, Util) {
        'use strict';
        var self = this;
        self.locations = [];
        self.loadLocked = false;
        self.pending = [];
    
        self.findLocations = function () {
            var d = $q.defer();
            if (self.locations.length > 0) {
                d.resolve(self.locations);
            }
            else if (self.locations.length === 0 && !self.loadLocked) {
                self.loadLocked = true;
                DB.query("SELECT * FROM locations WHERE kind = 'active'")
                       .then(function (resultSet) {
                           var locations = DB.fetchAll(resultSet);
                           self.locations.
                               push.apply(self.locations, locations);
                           self.loadLocked = false;
                           d.resolve(self.locations);
                           self.pending.forEach(function (d) {
                               d.resolve(self.locations);
                           });
                       }, Util.handleError);
                } else {
                    self.pending.push(d);
                }
    
                return d.promise;
            };
    })
    

    这个例子有点吵,因为它有一些“线程”代码来确保如果相同的 Promise 被触发两次,它只对 DB 运行一次。一般的要点是表明 DB.query 返回一个承诺。查询方法后面的“then”使用数据库服务来获取所有数据并将其添加到我的本地内存空间中。所有这些都由返回变量 d.promise 的 self.findLocations 协调。

    您的代表也类似。控制器可以让你的 DAL 服务,比如我的 LocationService,由 AngularJS 注入。如果您使用的是 AngularJS UI,您可以让它解析数据并将其传递到列表中。

    最后,我对这家伙的代码唯一的问题是 db 应该来自这个代码。

    var dbMaker = ($window.sqlitePlugin || $window);
    

    原因是该插件在 Apache Ripple 中不起作用。由于该插件可以很好地镜像浏览器的 Web SQL 界面,因此这个简单的小改动将使 Ripple 能够运行您的 Ionic 应用程序,同时仍然允许您在真实设备中使用 SQLite。

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-15
      • 1970-01-01
      • 2015-11-24
      • 1970-01-01
      • 2016-10-24
      • 2015-02-04
      • 1970-01-01
      • 2012-10-19
      相关资源
      最近更新 更多