這個問題讓我難堪。轉儲交易後IndexedDB密鑰生成器重置
由於某些原因,indexedDB中的自動增量密鑰生成器在使用put-transaction執行和更新現有對象後重置,導致覆蓋數據庫中的數據。
對於我的應用程序,我使用了一個爲angularJS自我編寫的IndexedDB服務,並實現了所有基本的CRUD功能。 我也可以補充說我正在用Ionic Framework開發,即使我懷疑這是責任。
考慮到服務是一個工作進行中,我已經通過自動增量策略讓對象存儲的關鍵路徑默認爲「id」。 然而,給定商店的指數取決於用戶在特定對象中的決定。 作爲一個例子:
dbHelper.objectStores = [{'employees',
indices: [{indexName: 'name', isUnique: false},
{indexName: 'phone', isUnique: true}]}];
這,除非在db已經創建,創建對象存儲「僱員」與索引「名稱」和「電話」,在「電話」必須是唯一值而'名稱'不會。
這裏是openDB函數的實現。 請注意,dbHelper.objectStores應該是空的,因爲它是由用戶在打開數據庫之前分配這些屬性(或者它是默認的)。
angular.module('dbProvider', [])
.factory('$db', ['$window', function($window) {
// DB Object
var dbHelper = {};
// Properties - Are given defaults unless assigned manually by user before openDB is invoked.
dbHelper.dbName = 'defaultDB';
dbHelper.dbVersion = 1;
dbHelper.objectStores = [];
dbHelper.openDB = function(onCompleteCallback, onErrorCallback) {
console.log('Atempting to open db with name ' + dbHelper.dbName + '.');
var request = $window.indexedDB.open(dbHelper.dbName, dbHelper.dbVersion);
// Invoked by indexedDB if version changes
request.onupgradeneeded = function(e) {
console.log('Version change. Current version: ' + dbHelper.dbVersion);
var db = e.target.result;
e.target.transaction.onerror = onErrorCallback;
if(dbHelper.objectStores.length === 0) {
dbHelper.objectStores.push({name:'defaultStore', indices: []});
}
for(var store in dbHelper.objectStores) {
if(db.objectStoreNames.contains(dbHelper.objectStores[store].name)) {
console.log(dbHelper.objectStores[store].name + ' deleted.');
db.deleteObjectStore(dbHelper.objectStores[store].name);
}
var newStore = db.createObjectStore(dbHelper.objectStores[store].name, {keyPath: "id", autoIncrement: true});
for(var index in dbHelper.objectStores[store].indices) {
newStore.createIndex(dbHelper.objectStores[store].indices[index].indexName,
dbHelper.objectStores[store].indices[index].indexName,
{unique : dbHelper.objectStores[store].indices[index].isUnique});
}
console.log(dbHelper.objectStores[store].name + ' created.');
}
};
request.onsuccess = function(e) {
console.log('DB ' + dbHelper.dbName + ' open.');
dbHelper.indexedDB.db = e.target.result;
onCompleteCallback();
};
request.onerror = onErrorCallback;
};
下面是一些的CRUD功能(那些有問題):
dbHelper.findItemWithIndex = function(keyValue, storename,
onCompleteCallback,onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var index = store.index(keyValue.key);
index.get(keyValue.value).onsuccess = function(event) {
onCompleteCallback(event.target.result);
};
};
dbHelper.addItemToStore = function(item, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.add(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.deleteItemFromStore = function(itemId, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.delete(itemId);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.updateItem = function(item, storename, onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.put(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
最後,從其中交易被調用控制器的代碼。 這裏的策略是,在第一次保存項目時,使用addItemToStore函數將項目添加到數據庫,然後是updateItem函數。 第一次添加之後,該對象會立即被提取,以便使用來自數據庫的指定ID繼續使用該對象。
$scope.updateTemplate = function() {
console.log('Saving..');
var onCompleteCallback = {};
if(!$scope.formTemplate.firstSave) {
onCompleteCallback = $scope.updateModel;
} else {
$scope.formTemplate.firstSave = false;
onCompleteCallback = $scope.setId;
}
$db.updateItem($scope.formTemplate, $scope.objectStore.name,
onCompleteCallback, $scope.dbError);
};
$scope.newItem = function() {
$db.addItemToStore($scope.formTemplate, $scope.objectStore.name,
$scope.setId, $scope.dbError);
};
$scope.setId = function() {
$db.findItemWithIndex(
{key: 'title',
value: $scope.formTemplate.title},
$scope.objectStore.name,
function(result) {
console.log(JSON.stringify(result));
$scope.formTemplate = result;
},
function(error) {
$scope.dbError(error);
});
}
它在這裏一切都會到地獄。 我添加一個對象,回到另一個視圖,並在id = 1的列表中找到它。 我添加了另一個對象,回到列表視圖,並且它的id = 2。 而且等等等等..
然後,更新或者與$ scope.updateTemplate功能,這也就像一個魅力的對象後,事情就變得有趣:
添加的下一個對象獲得ID = 1,並從早期完全擦除舊的舊數字。
接下來的對象也會得到id,導致它們替換已經存在的對象。
這是什麼原因造成的?
爲了測試,我在OS 10.10中使用Safari 8,並且我正在部署到LGG2和KitKat 4.4.2。
我建議你減少你的問題,以重現該問題只需要在相關代碼/信息。有可能這樣做,你會發現你自己的問題。在任何情況下,加入了plunker /的jsfiddle幫助其他幫助您調試代碼。 – 2014-11-03 06:06:33
我們有完全相同的問題。你最終做了什麼來解決這個問題?我們在想,也許我們應該停止使用自動增量,並創建自己的密鑰。 – Justin 2015-08-03 20:58:04