Хранение базы данных SQLite с помощью Android и Phonegap

Я разрабатываю приложение Android Cordova/Phonegap, где я хочу использовать базу данных SQLite. Я использовал пример из официальной документации.

// Wait for device API libraries to load
//
document.addEventListener("deviceready", onDeviceReady, false);

// Populate the database
//
function populateDB(tx) {
    tx.executeSql('DROP TABLE IF EXISTS DEMO');
    tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
    tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")');
    tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")');
}

// Query the database
//
function queryDB(tx) {
    tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}

// Query the success callback
//
function querySuccess(tx, results) {
    var len = results.rows.length;
    console.log("DEMO table: " + len + " rows found.");
    for (var i=0; i<len; i++){
        console.log("Row = " + i + " ID = " + results.rows.item(i).id + " Data =  " + results.rows.item(i).data);
    }
}

// Transaction error callback
//
function errorCB(err) {
    console.log("Error processing SQL: "+err.code);
}

// Transaction success callback
//
function successCB() {
    var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
    db.transaction(queryDB, errorCB);
}

// device APIs are available
//
function onDeviceReady() {
    var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
    db.transaction(populateDB, errorCB, successCB);
}

Хотя это, похоже, работает (база данных создается и заполняется без ошибок, и я получаю записанные данные обратно с запросом), мне интересно, как база данных хранится на моем устройстве. Для отладки я использую аппаратный телефон с Android 4.1.1.

База данных находится под /data/data/<myapppackage>/app_database/file__0/0000000000000001.db. Теперь я хотел экспортировать базу данных и проанализировать ее вручную на моем компьютере с помощью SQLiteManager, но, похоже, изменения не записываются в файл db.

Однако при рассмотрении каталога /data/data/<myapppackage>/app_database/file__0/ я обнаружил два временных файла 0000000000000001.db-shm и 0000000000000001.db-wal, чьи метки времени меняются каждый раз, когда я выполняю операцию с базой данных, но никогда не сам файл db.

Мой вопрос: почему изменения никогда не записываются в файл постоянной базы данных? Кажется, что не существует способа закрыть соединение с телефонной связью, и даже убить приложение вручную не записывает изменения в файл .db. Я не уверен, что я сделал не так.

Кто-нибудь видит проблему здесь?

Ответ 1

tx.executeSql('DROP TABLE IF EXISTS DEMO');

Эта строка выше удаляет таблицу с именем DEMO при каждом запуске мобильного приложения PhoneGap.

И я просто хотел сказать, что мне нравится ваш код. Это дает очень хорошее представление о том, "что делать" для любого приложения PhoneGap или Cordova. Это очень поможет любому, кто впервые войдет в мир SQLite.

Ваш код очень чистый, чтобы читать и понимать по сравнению с кодами, написанными на официальном сайте плагина Cordova/PhoneGap SQLite на GitHub.

Мой друг, который также работает техническим директором компании и имеет большой опыт работы с SQLite, сказал мне, что нет необходимости закрывать соединение базы данных SQLite вручную, а также очень рекомендуется SQLite.

И для всех, кто ищет SQLite для информации о PhoneGap/Cordova -

Скажем, у вас есть таблица с именем mytable и хотите хранить значения "красивый" и "дельфин"

Если вы хотите выполнить операцию на SQLite мобильного устройства, например, планшета или телефона, не забудьте вызвать его таким образом

В исходном коде есть следующее:

function insertNewLine(tx) 
{
   tx.executeSql("INSERT INTO mytable (word, meaning) VALUES (?,?)", [ var1 , var2 ]);
}

и сохраните "красивые" внутри var1 и "дельфин" внутри var2 и

выполните следующую инструкцию для выполнения инструкции вставки SQL и затем сохраните ее внутри устройства.

db.transaction(insertNewLine);   

Не напрямую вызвать insertNewLine (tx)

Не напрямую вызывать tx.executeSql(/* SQL INSERT STATEMENT */); в исходном коде JavaScript

И не включать значения прямо в инструкцию SQL-запроса, а затем запускать инструкцию SQL, которая содержит значения, которые вы хотите сохранить в базе данных.

Другими словами, следующее неверно

tx.executeSql('INSERT INTO mytable (word, meaning) values (beautiful, dolphin)');

Это неверно, потому что значения, которые вы хотите сохранить, "красивые" и "дельфины" включены в инструкцию SQL. Они должны быть раздельными.

Ниже приведен правильный способ запуска INSERT SQL

tx.executeSql("INSERT INTO mytable (word, meaning) VALUES (?,?)", [ var1 , var2 ]);
 // Notice that the values you want to store, beautiful and dolphin
 // are separate from the SQL INSERT INTO statement

а затем выполнить всю транзакцию базы данных, включив в код JavaScript код

db.transaction(insertNewLine);

не приведенный ниже код

tx.executeSql("INSERT....."); // this will not save your values onto the device

не приведенный ниже код

insertNewLine(tx); // this will not save your values onto the device either.  

И для использования инструкции SELECT SQL, используйте следующий код

// Get all lines in the table
//
function viewthelastglory(tx)  
{
    tx.executeSql( 'SELECT * FROM CUSTOMTABLE', [], querySuccess, errorcode );
}

// Deal with the lines 
//
function querySuccess(tx, results) 
{
   var len = results.rows.length; var  queryresult = "all entries ";

   for (var i = 0 ; i < len ; i++)
   {
       queryresult =  queryresult +  

       " Row - " + i + 
       " Word - " + results.rows.item(i).word + 
       " Meaning - " + results.rows.item(i).meaning;
   }

// and now, you can use the queryresult variable to use the values   
}

function errorcode(errorhaha) 
{
    alert("Error Code " + errorhaha.code + " Error Message " + errorhaha.message);
}

И затем выполните транзакцию базы данных

db.transaction(viewthelastglory);

Если вы пытаетесь выбрать один из SQLite, WebSQL и IndexedDB, помните, что я некоторое время искал вокруг stackoverflow и узнал, что

  • Никто не любит IndexedDB из-за его сложности.
  • IndexedDB несовместим со многими типами и версиями мобильной ОС
  • WebSQL устарел от W3C
  • WebSQL возвращает результаты 673K, но SQLite возвращает результаты 1800K. IndexedDB возвращает результаты 300K в Google
  • Среди IndexedDB, SQLite и WebSQL SQLite является единственным с официальным сайтом.

Следующая команда в командной строке, находящаяся в каталоге вашего проекта Cordova, установит плагин SQLite в проект Cordova

cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin

Ответ 2

Решение: Отладка вашего приложения с помощью эмулятора вместо физического устройства.

Запустите приложение с emulator вместо физического устройства. Файл database находится в /data/data/YOUR_PACKAGE_NAME/app_database/. Вы можете pull файл database и просматривать таблицы и данные.

Ответ 3

В режиме WAL любые изменения записываются в файл -wal; сам файл базы данных не обновляется до тех пор, пока не будет выполнена контрольная точка .

Если есть файл -wal, вы также должны его скопировать.