Cordova SQLite:无法读取null的属性“transaction”

时间:2015-02-11 20:59:26

标签: javascript android sqlite cordova ionic-framework

我正在尝试将SQLite集成到我的Ionic应用程序中,但是当我尝试在数据库中查询设备上的数据时,我在通过浏览器进行远程调试或测试时不断获得Cannot read property 'transaction' of null

所以我把我的所有配置,控制器和工厂拆分成单独的文件,全部按功能/模块分组,所以我将每个模块的配置文件注入主应用程序,然后在配置文件中我注入了控制器和工厂。

我不确定我构建应用程序的方式是否会破坏某些内容?

下面我列出了所有相关文件,

app.js

var app = angular.module('app', ['ionic', 'ngCordova', 'app.config', 'login.config']);

app.run(['$rootScope', '$ionicPlatform', 'DB', function($rootScope, $ionicPlatform, DB) {

    $ionicPlatform.ready(function() {

        if (window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }

        if (window.StatusBar) {
            StatusBar.styleDefault();
        }

        if(navigator.splashscreen) {
            navigator.splashscreen.hide();
        }

        DB.init();

    });

}]);

app.config.js

var app = angular.module('app.config', ['app.controller', 'app.factory']);

app.config(function($stateProvider, $urlRouterProvider, $httpProvider) {

    $stateProvider
        .state('app', {
            url: "/app",
            abstract: true,
            templateUrl: "templates/menu.html",
            controller: 'appController'
        });

    $urlRouterProvider.otherwise('/login');

});

app.constant('DB_CONFIG', {
    name: 'database.db',
    tables: [
        {
            name: 'users',
            columns: [
                {name: 'id', type: 'integer primary key'},
                {name: 'username', type: 'text'},
                {name: 'password', type: 'text'},
                {name: 'api_key', type: 'text'},
                {name: 'active', type: 'integer'}
            ]
        }
    ]
});

app.factory.js

var appFactory = angular.module('app.factory', []);

appFactory.factory('DB', ['$q', '$cordovaSQLite', 'DB_CONFIG', function($q, $cordovaSQLite, DB_CONFIG) {

    var db = null;

    var init = function() {

        db = $cordovaSQLite.openDB({ name: DB_CONFIG.name });
        // I use this when testing in browser db = window.openDatabase(DB_CONFIG.name, '1.0', 'database', -1);

        _.each(DB_CONFIG.tables, function(table) {

            var columns = [];

            _.each(table.columns, function(column) {

                columns.push(column.name + ' ' + column.type);

            });

            var sql = 'CREATE TABLE IF NOT EXISTS ' + table.name + ' (' + columns.join(',') + ')';

            console.log('Table ' + table.name + ' initialized');

            query(sql);

        });

    };

    var query = function(sql, bindings) {

        bindings = typeof bindings !== 'undefined' ? bindings : [];

        return $cordovaSQLite.execute(db, sql, bindings);

    };

    var fetchAll = function(result) {

        var output = [];

        for (var i = 0; i < result.rows.length; i++) {
            output.push(result.rows.item(i));
        }

        return output;
    };

    var fetch = function(result) {
        return result.rows.item(0);
    };

    return {
        init: init,
        query: query,
        fetchAll: fetchAll,
        fetch: fetch
    };
}]);

login.config.js

var loginConfig = angular.module('login.config', ['ionic', 'login.controller']);

loginConfig.config(function($stateProvider) {

    $stateProvider

        .state('login', {
            url: "/login",
            templateUrl: "modules/login/views/login.html",
            controller: 'loginController'
        });

});

login.controller.js

var loginController = angular.module('login.controller', []);

loginController.controller('loginController', ['$scope', '$state', 'DB', function($scope, $state, DB) {

    $scope.doLogin = function() {

        var username = this.username;
        var password = this.password;

        DB.query('SELECT * FROM users WHERE username = ? and password = ?', [username, password]).then(function(result){
            console.log(result);
        }, function(error){
            console.log(error);
        });

    };

}]);

用户已经插入到数据库中,有时它可以工作,我得到了结果,大部分时间都没有,我得到了上面提到的错误。

我假设这是因为在我查询数据库之前,DB没有及时初始化?

如果是这样,有没有办法在查询之前100%确定数据库已加载?

6 个答案:

答案 0 :(得分:1)

我有同样的问题,数据库没有正确初始化(这是随机发生的),使用带延迟的promise和$ ionicPlatform.ready(function(){});

参考:https://gist.github.com/borissondagh/29d1ed19d0df6051c56f

示例:

angular.module('myapp.services', [])

.factory('DBA', function($cordovaSQLite, $q, $ionicPlatform) {
  var self = this;

  // Handle query's and potential errors
  self.query = function (query, parameters) {
    parameters = parameters || [];
    var q = $q.defer();

    $ionicPlatform.ready(function () {
      $cordovaSQLite.execute(db, query, parameters)
        .then(function (result) {
          q.resolve(result);
        }, function (error) {
          console.warn('DB error found');
          console.warn(error);
          q.reject(error);
        });
    });
    return q.promise;
  }

  // Process a result set
  self.getAll = function(result) {
    var output = [];

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

  // Process a single result
  self.getById  = function(result) {
    var output = null;
    output = angular.copy(result.rows.item(0));
    return output;
  }

  return self;
})

答案 1 :(得分:0)

如果只在需要时打开连接,它可能会有所帮助。 您保持连接打开,可能会超时。 我通常做的是打开一个连接,而不是查询我需要查询的内容,而不是关闭连接。

答案 2 :(得分:0)

我有同样的问题删除你的sqlLite插件并再次添加它 问题解决了!!!

cordova插件rm io.litehelpers.cordova.sqlite cordova插件添加io.litehelpers.cordova.sqlite

答案 3 :(得分:0)

$ cordovaSQLite.openDB现在需要一个强制位置参数。变化

db = $cordovaSQLite.openDB({ name: DB_CONFIG.name });

db = $cordovaSQLite.openDB({ name: DB_CONFIG.name, location:'default' });

答案 4 :(得分:0)

我有同样的问题。不知道为什么,但它与键盘插件有某种关联。

尝试:

@RunWith(Cucumber.class)
@CucumberOptions(plugin = { "pretty" }, features = { "<path_to_feature>" }, 
    glue = { "<optional_steps_location_java_file>" }, dryRun = true,
    tags = { "<optional_NOT_req_for_now>" })
public class RunMyCucumberTest {

}

https://forum.ionicframework.com/t/important-all-ionic-users-please-update-your-keyboard-plugin/46889

执行此操作后数据库工作正常。

答案 5 :(得分:0)

尝试再次安装SqlLite。

ionic cordova plugin add cordova-sqlite-storage
npm install @ionic-native/sqlite

有同样的问题。已解决此问题。