web-dev-qa-db-fra.com

Stockage de la base de données SQLite avec Android et Phonegap

Je développe une application Android Cordova/Phonegap sur laquelle je souhaite utiliser une base de données SQLite. J'ai utilisé l'exemple du fonctionnaire documentation

// 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);
}

Bien que cela semble fonctionner (la base de données est créée et remplie sans erreur, et je récupère les données écrites avec la requête), mais je me demande comment la base de données est stockée sur mon appareil. Pour le débogage, j'utilise un téléphone avec Android 4.1.1. 

La base de données se trouve sous /data/data/<myapppackage>/app_database/file__0/0000000000000001.db. Maintenant, je voulais exporter la base de données et l’analyser manuellement sur mon ordinateur avec SQLiteManager, mais il semble que les modifications ne sont pas écrites dans le fichier db. 

Cependant, lors de l'examen du répertoire /data/data/<myapppackage>/app_database/file__0/, j'ai trouvé les deux fichiers temporaires 0000000000000001.db-shm et 0000000000000001.db-wal, dont les horodatages sont modifiés à chaque fois que j'effectue une opération de base de données, mais jamais le fichier db proprement dit.

Ma question est la suivante: pourquoi les modifications ne sont-elles jamais écrites dans le fichier de base de données persistant? Il ne semble pas y avoir de moyen de fermer une connexion de base de données avec phonegap, et même tuer l'application manuellement ne permet pas d'écrire les modifications dans le fichier .db. Je ne suis pas sûr de ce que j'ai mal fait.

Quelqu'un a vu le problème ici?

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

La ligne ci-dessus supprime la table nommée DEMO chaque fois que vous démarrez votre application mobile PhoneGap

Et je voulais juste vous dire que j'aime votre code. Cela donne un très bon indice sur "quoi faire" pour les applications PhoneGap ou Cordova de quiconque. Cela aidera grandement tous ceux qui entrent dans le monde de SQLite pour la première fois. 

Votre code est très propre à lire et à comprendre comparé aux codes écrits sur le site officiel du plugin Cordova/PhoneGap SQLite sur GitHub. 

Mon ami, qui travaille également en tant que CTO d'une entreprise et possède une grande expérience de SQLite, m'a dit qu'il n'était pas nécessaire de fermer manuellement une connexion à une base de données SQLite.

Et pour tous ceux qui recherchent des informations SQLite pour PhoneGap/Cordova -

Disons que vous avez une table nommée mytable et que vous voulez stocker les valeurs "beautiful" et "dauphin" 

Lorsque vous souhaitez effectuer une opération sur le SQLite d'un périphérique mobile, tel qu'une tablette ou un téléphone, rappelez-vous de l'appeler ainsi.

Avoir les éléments suivants dans votre code source

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

et stocker "beau" dans var1 et "dolphin" dans var2 et

effectuez l'instruction suivante afin d'exécuter l'instruction d'insertion SQL, puis enregistrez-la à l'intérieur du périphérique.

db.transaction(insertNewLine);   

Ne pas appeler directement insertNewLine (tx) 

Ne pas appeler directement tx.executeSql (/ * SQL INSERT STATEMENT * /); dans votre code source JavaScript

Et ne pas inclure les valeurs directement dans l'instruction de requête SQL, puis exécuter l'instruction SQL qui inclut les valeurs que vous souhaitez stocker dans la base de données.

En d'autres termes, ce qui suit est incorrect  

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

Ce qui précède est incorrect car les valeurs que vous souhaitez stocker, "beautiful" et "dolphin" sont incluses dans l'instruction SQL. Ils devraient être séparés. 

Voici la manière correcte d’exécuter le fichier 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

puis effectuez la transaction de base de données complète en incluant les éléments suivants dans votre code JavaScript

db.transaction(insertNewLine);

pas le code ci-dessous

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

pas le code ci-dessous non plus

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

Et pour utiliser l'instruction SELECT SQL, procurez-vous le code suivant

// 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);
}

Et ensuite, effectuez la transaction de base de données

db.transaction(viewthelastglory);

Si vous essayez de choisir entre SQLite, WebSQL et IndexedDB, n’oubliez pas que j’ai cherché pendant un moment autour de stackoverflow et que j’ai appris que 

  • Personne n'aime IndexedDB en raison de sa complexité 
  • IndexedDB est incompatible avec de nombreux types et versions d'OS mobiles 
  • WebSQL est obsolète par le W3C
  • WebSQL renvoie 673K ​​résultats, mais SQLite renvoie 1800K résultats. IndexedDB renvoie 300 000 résultats sur Google
  • Parmi IndexedDB, SQLite et WebSQL, SQLite est le seul à posséder un site Web officiel. 

La commande suivante sur la ligne de commande lorsque vous êtes dans le répertoire de votre projet Cordova installera le plug-in SQLite dans votre projet Cordova.

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

La solution est: déboguez votre application avec un émulateur au lieu d'un périphérique physique.

Exécutez votre application avec emulator à la place du périphérique physique. Vous trouverez votre fichier database dans /data/data/YOUR_PACKAGE_NAME/app_database/. Vous pouvez pull le fichier database et parcourir les tables et les données. 

0
Lekhnath

En mode WAL , toutes les modifications sont écrites dans le fichier -wal; le fichier de base de données lui-même n'est pas mis à jour tant qu'un point de contrôle n'est pas terminé.

S'il existe un fichier -wal, vous devez également le copier.

0
CL.