【问题标题】:Cordova SQLite: Cannot read property 'transaction' of nullCordova SQLite:无法读取 null 的属性“事务”
【发布时间】:2015-02-11 20:59:25
【问题描述】:

我正在尝试将 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);
        });

    };

}]);

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

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

如果是这样,有没有一种方法可以让我在查询之前 100% 确保数据库已加载?

【问题讨论】:

    标签: javascript android sqlite cordova ionic-framework


    【解决方案1】:

    我遇到了同样的问题,数据库没有正确初始化(这是随机发生的),将 promise 与 defer 和 $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;
    })
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 感谢您的回复!我希望它不必达到那个,必须有更好的方法?在一个会话中多次打开和关闭数据库连接似乎太过分了。
      • 在需要时打开连接并不是一件坏事。如果人们打开应用程序但他们不使用它,您将保持与数据库的连接
      【解决方案3】:

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

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

      【讨论】:

      • 我的项目已经有了这个键盘插件,cordovaSqlite插件今天突然停止工作了,不知道为什么
      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

        再次尝试安装 SqlLite。

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

        有同样的问题。以此修复。

        【讨论】:

          【解决方案6】:

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

          试试:

          ionic plugin rm ionic-plugin-keyboard    
          ionic plugin add ionic-plugin-keyboard
          

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

          完成此操作后,数据库工作正常。

          编辑:

          这些命令正在更新中。

          ionic cordova plugin rm ionic-plugin-keyboard
          ionic cordova plugin add ionic-plugin-keyboard
          

          【讨论】:

            猜你喜欢
            • 2018-11-30
            • 2018-04-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-01-29
            • 2016-11-24
            相关资源
            最近更新 更多