javascript - 持久性JS : Updating an existing database using migrate()

标签 javascript html persistence

我目前正在尝试使用 PersistenceJS 的迁移插件对现有数据库进行更改。我可以很好地在数据库中添加/编辑/删除项目——但是……

  • 如何向现有(!)表中添加一列?
  • 如何更改现有 (!) 列的类型,例如从“文本”到“整数”?

  • 这些更改应保留当前存在的数据。

遗憾的是,文档有点稀缺,也许你能帮忙?

这是当前有效设置:

persistence.store.websql.config(persistence, 'tododatabase', 'todos are fun', 5*1024*1024);

var Todo = persistence.define('Todo', {
    task: 'TEXT',
    priority: 'INT',
    done: 'BOOL'
});

persistence.schemaSync();

function addTodo( item ){
    var todo = new Todo();
    todo.task = item.task;
    todo.priority = item.priority;
    todo.done = item.done;

    persistence.add(todo);
    persistence.flush();
};

function deleteTodo( item, callback ){
    // item.id was created automatically by calling "new Todo()"
    Todo.all().filter('id','=', item.id ).destroyAll( function(){
        persistence.flush( callback );
    });
};

有点的迁移代码:

persistence.defineMigration(1, {
    up: function() {
        this.createTable('Todo', function(t){
            t.text('task');
            t.integer('priority');
            t.boolean('done');
        });
    },
    down: function() {
        this.dropTable('Todo');
    }
});

persistence.defineMigration(2, {
    up: function() {
        this.addColumn('Todo', 'due', 'DATE');
    },
    down: function() {
        this.removeColumn('Todo', 'due');
    }
});


function migrate( callback ){
    console.log('migrating...');
    persistence.migrations.init( function(){
        console.log('migration init');
        // this should migrate up to the latest version, in our case: 2
        persistence.migrate( function(){
            console.log('migration complete!');
        } );
    });
}

结果……

  1. 调用 migrate() 只会记录“迁移初始化”,不会调用完整的处理程序,不会创建“到期”列
  2. 在调用 migrate() 之前不调用 schemaSync() 正如 Zef Hemel 自己在 this post 中提出的那样产生与 1 相同的结果。
  3. 将第一行更改为 persistence.store.websql.config(persistence, 'newdatabase', 'testing migration', 5*1024*1024);,不调用 schemaSync(),只调用migrate() 将成功记录“迁移完成!” — 但它是在一个新的、完全空的数据库“newdatabase”中这样做的,该数据库当然不会保留任何现有数据。

总结

有一个数据库是使用 persistence.store.websql.config(...), persistence.define('Todo',...) 创建的和 persistence.schemaSync()

我现在想保留该数据库中已经存在的所有数据,但又想

  • 将列 priority 的类型从“整数”更改为“文本”
  • 向所有现有待办事项添加类型为“日期”的到期

如果你能把我推向正确的方向,我将不胜感激!

谢谢!

最佳答案

我终于让它工作了。我想指出一些与我的初始要求有关的问题,以供将来引用。看一下第一个迁移定义:

persistence.defineMigration(1, {
    up: function() {
        this.createTable('Todo', function(t){
        ...


毫不奇怪,createTable 将执行此操作:它将执行 SQL 语句 'CREATE TABLE Todo ...',如果有已经具有名称 Todo 的表。这就是为什么它适用于新数据库,但不适用于现有数据库。请记住:我已经有一个实时数据库,其中包含需要更新的表“Todo”。如果您是新手(即您没有使用过 schemaSync),createTable 工作得很好。由于 Migrations 插件不提供 createTableIfNotExists 方法,我需要使用 executeSql 如下:

persistence.defineMigration(1, {
    up: function() {
        this.executeSql('CREATE TABLE IF NOT EXISTS Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, done BOOL)');
        ...


现在从架构版本 0 到 1 的迁移成功了,到版本 2 的迁移也成功了。

随着迁移到版本 3,priority 列的类型需要从 int 更改为 text。这通常使用 ALTER COLUMN SQL 命令来完成,Web SQL/SQLite 不支持该命令。参见 Omitted Features for SQLite .

使用 SQLite 更改列需要 4 个步骤的解决方法:

persistence.defineMigration(3, {
    up: function() {
        // rename current table
        this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
        // create new table with required columns and column types
        this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority TEXT, done BOOL)');
        // copy contents from old table to new table
        this.executeSql('INSERT INTO Todo(id, task, priority, done) SELECT id, task, priority, done FROM OldTodo');
        // delete old table
        this.executeSql('DROP TABLE OldTodo');
    },
    ...


当然,改变列类型后,'Todo'的实体定义也要改变:

var Todo = persistence.define('Todo', {
    task: 'TEXT',
    priority: 'TEXT', // was 'INT'
    due: 'DATE',
    done: 'BOOL'
});


最后,完整的源代码:

persistence.store.websql.config(persistence, 'tododatabase', 'todos are fun', 5*1024*1024);

// persistence.debug = true;

//v0 + v1
// var Todo = persistence.define('Todo', {
//  task: 'TEXT',
//  priority: 'INT',
//  done: 'BOOL'
// });

//v2
// var Todo = persistence.define('Todo', {
//  task: 'TEXT',
//  priority: 'INT',
//  due: 'DATE',
//  done: 'BOOL'
// });

//v3
var Todo = persistence.define('Todo', {
    task: 'TEXT',
    priority: 'TEXT',
    due: 'DATE',
    done: 'BOOL'
});


persistence.defineMigration(1, {
    up: function() {
        this.executeSql('CREATE TABLE IF NOT EXISTS Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, done BOOL)');
    },
    down: function() {
        this.dropTable('Todo');
    }
});

persistence.defineMigration(2, {
    up: function() {
        this.addColumn('Todo', 'due', 'DATE');
    },
    down: function() {
        this.removeColumn('Todo', 'due');
    }
});

persistence.defineMigration(3, {
    up: function() {
        // rename current table
        this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
        // create new table with required columns
        this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority TEXT, due DATE, done BOOL)');
        // copy contents from old table to new table
        this.executeSql('INSERT INTO Todo(id, task, priority, due, done) SELECT id, task, priority, due, done FROM OldTodo');
        // delete current table
        this.executeSql('DROP TABLE OldTodo');
    },
    down: function() {
        this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
        this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, due DATE, done BOOL)');
        this.executeSql('INSERT INTO Todo(id, task, priority, due, done) SELECT id, task, priority, due, done FROM OldTodo');
        this.executeSql('DROP TABLE OldTodo');
    }
});


function migrate( callback ){
    console.log('migrating...');
    persistence.migrations.init( function(){
        console.log('migration init');
        persistence.migrate( function(){
            console.debug('migration complete!');
            callback();
        } );
    });
};

migrate( onMigrationComplete );

function onMigrationComplete(){
    // database is ready. do amazing things...
};

关于javascript - 持久性JS : Updating an existing database using migrate(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24204554/

相关文章:

javascript - Angular 2/4/5 系统的良好架构

java - 有没有像 Python 的适用于 Android/Java 的 Shelve 这样的 SQL 替代品?

java - 领域层和持久层的区别

javascript - jQuery 中使用变量的多个动态选择器

Javascript 延时效果 : displaying 30 images/second (read for more detail)

javascript - 如何切换多个字体图标

javascript - 溢出 : Scroll on Y and Visible on X

spring - 使用 PostGIS Geometry Hibernate 持续失败

javascript - 使用 localStorage 和 $localStorage 使用 Angular 1 存储字符串的不同值。

html - Web Developer 工具栏真的有保存按钮来保存在 Firebug 中修改的 CSS 吗?