在phonegap中嵌套的sqlite事务

时间:2013-04-15 18:50:34

标签: javascript android ios sqlite cordova

我的主要目标是在sqlite中为db / android保存以下结构。 相应的表将包含外键,这些外键由编译指示处理。

var tempData = [{
    name : "foo",
    values : [{
            child : "foofoo",
            value : [1, 2, 3]
        }, {
            child : "foofaa",
            value : [5, 6, 7]
        }
    ]
}, {
    name : "bar",
    values : [{
            child : "barbar",
            values : [11, 22, 33]
        }, {
            child : "barbala",
            values : [44, 55, 66]
        }
    ]
}, {
    name : "baz",
    values : [{
            child : "bazbaz",
            values : [444, 333, 222]
        }, {
            child : "bazbaazar",
            values : [999, 888, 777]
        }
    ]
}];

为了坚持上述结构,我写了下面的代码片段。 这是用于克服嵌套事务的传统方法吗? 或者我必须遵循一些标准?

以下代码工作正常,但不保证执行顺序。我在输出中看到一些随机行为。如何保证嵌套事务的同步行为。我已经抓了很多网站,但找不到坦诚的解决方案。请帮忙

db.transaction(setupTable, dbErrorHandler, getEntries);
function setupTable(tx) {
doLog("before execute sql...");
tx.executeSql('CREATE TABLE IF NOT EXISTS mainTest(mainKey INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT  NOT NULL)');
tx.executeSql('CREATE TABLE IF NOT EXISTS child(PKEY INTEGER PRIMARY KEY AUTOINCREMENT,parentKey INTEGER,children TEXT  NOT NULL,FOREIGN KEY(parentKey) REFERENCES mainTest(mainKey))');
tx.executeSql('CREATE TABLE IF NOT EXISTS secondChild(SCKEY INTEGER PRIMARY KEY AUTOINCREMENT,spkey INTEGER,sales INTEGER,FOREIGN KEY(spkey) REFERENCES child(PKEY))');
doLog("after execute sql...");}
function getEntries(tx) {

//doLog("get entries");
/*dbShell.transaction(function(tx) {
tx.executeSql("select id, title, body, updated from notes order by updated desc",[],renderEntries,dbErrorHandler);
}, dbErrorHandler);*/

doLog("get entries");
db.transaction(function (tx) {
    _.each(tempData, function (item) {
        name = item.name;
        tx.executeSql('INSERT INTO mainTest (name) VALUES("' + name + '")', [], function (tx, result) {
            doLog("in child insert" + item.values);
            doLog("in child insert" + JSON.stringify(tempData));
            _.each(item.values, function (item) {
                doLog("in " + item.child);
                tx.executeSql('INSERT INTO child (parentKey,children) VALUES((select mainKey from mainTest where name = "' + name + '"),"' + item.child + '")', [], function (tx, result) {
                    _.each(item.values, function (itemNew) {
                        tx.executeSql('INSERT INTO secondChild (spkey,sales) VALUES((select PKEY from child where children = "' + item.child + '"),"' + itemNew + '")', [], function (tx, result) {}, dbErrorHandler);
                    });
                }, dbErrorHandler);
                doLog("after secondChild Insertion");
            });
            doLog("after child insertion");
        }, dbErrorHandler);
        doLog("after main insertion");
    });
}, dbErrorHandler);}

2 个答案:

答案 0 :(得分:1)

我想我明白你的观点。

让我试着帮助:

我正在使用类似的代码,以便尝试保证特定的交易顺序,但在我个人看来(由于最近的经验),你必须寻找嵌套交易的解决方法...... 我的问题与我必须将我的phonegap应用程序带到WinPhone 8的时间有关,其中数据库的功能不是本机可用于cordova,第一个解决方案是包含/开发插件。我找到的那个无法处理嵌套事务,你可以想象重写/重新设计程序有多难:/ 考虑到javascript的异步模型我找到了一个答案:我创建了自定义事件来确定事务是否已完成并且在该事件的监听器内,运行下一个事务。

//event var
var EVENT_TRANSACTION_ENDED_ = document.createEvent('Event');
//init the event
EVENT_TRANSACTION_ENDED_.initEvent('EVENT_TRANSACTION_ENDED_', true, true);
//listener to the event
document.addEventListener('EVENT_TRANSACTION_ENDED_', onEventFunctionHandler, false);

//first transaction
db.transaction(function(tx){
    //sample query
    tx.executeSql('SELECT * FROM TABLE', [], function(tx){
        //notify first transaction ended
        console.log('First transaction');
        setTimeout('document.dispatchEvent(EVENT_TRANSACTION_ENDED_);', 100);
    }, dbErrorHandler);
}, dbErrorHandler);

//
function onEventFunctionHandler(e){
    //second transaction
    db.transaction(function(tx){
        //sample query
        tx.executeSql('SELECT * FROM ANOTHER_TABLE', [], function(tx){
            //notify SECOND transaction ended
            console.log('SECOND transaction');
        }, dbErrorHandler);
    }, dbErrorHandler);
}

这对我有用,希望这有帮助。

答案 1 :(得分:1)

您必须使用tx.executeSql成功回调函数。优点还在于,如果第一个SQL语句中存在错误,则第二个SQL语句将不会执行。因此,您不会在数据库中出现不一致。 这对我有所帮助:

        db.transaction(function(tx){
            tx.executeSql('DELETE FROM object WHERE object_id IN(1,2)');
            }, errorCB, function(){
            db.transaction(function(tx){
                tx.executeSql('INSERT INTO object '+values_object);
                }, errorCB, successCB
            );
            }
        );

线索是执行第二个事务作为第一个事务的成功回调。所以语句按照定义的顺序执行。