1

我的主要目标是将以下结构保留在 android/IOS 的 sqlite 中的数据库中。相应的表将由 pragma 处理的外键组成。

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

2 回答 2

2

您必须在 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
            );
            }
        );

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

于 2016-10-07T21:30:12.790 回答
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);
}

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

于 2013-05-27T15:00:17.130 回答