【问题标题】:Using onUpgrade doesn't work, am I missing something? Thank you使用 onUpgrade 不起作用,我错过了什么吗?谢谢
【发布时间】:2022-01-13 23:20:16
【问题描述】:

这是我的资产文件夹中的数据库名称,我看到有人说资产不可写。

public class DatabaseAssets_Milestones extends SQLiteOpenHelper {
    private static String dbName = "milestones.db";
    Context context;
    File dbFile;

这是我的构造函数。

    public DatabaseAssets_Milestones(@Nullable Context context) {
        super(context, dbName, null, 2);
        this.context = context;
        File DB_PATH = context.getDatabasePath(dbName);
        String db = DB_PATH.getAbsolutePath();
        dbFile = new File(db);

        if(!dbFile.exists()){
            if (!dbFile.getParentFile().exists()) {
                dbFile.mkdirs();
            }
            copyDataBase(dbFile.getPath());
        }
    }

这是我的复制数据库方法。

    private void copyDataBase(String dbPath){

        try{

            InputStream assetDB = context.getAssets().open("databases/"+"milestones.db");
            OutputStream appDB = new FileOutputStream(dbPath,false);

            byte[] buffer = new byte[1024];
            int length;
            while ((length = assetDB.read(buffer)) > 0) {
            appDB.write(buffer, 0, length);
            }
            appDB.flush();
            appDB.close();
            assetDB.close();

        }catch(IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

我在这里遗漏了什么吗?还是我的其他代码中的某些内容?

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + dbName);
        onCreate(db);
    }
}

【问题讨论】:

    标签: sqlite android-studio android-sqlite android-assets


    【解决方案1】:

    假设您有一个版本 1 的数据库并更改为版本 2,您所拥有的将:-

    1. 在数据库存在时跳过资产副本。
    2. 调用onUpgrade,后者调用onCreate,从数据库中删除表,然后为您留下一个没有删除表的数据库。

    onCreate 删除表的方法不会生成资产文件的副本。 从 onCreate 中调用 copyDatabase 方法可能会导致问题。

    如果您想要复制更改后的资产文件,那么您可能会发现 thisthis 很有用。

    如果您真的想在 onUpgrade 方法中将资产文件复制为新数据库(这样),那么您可以这样做:-

    1. 使用修改后的copyDataBase,你可以传递一个参数来修改copyDataBase的名字,从而导致

      1. 传递给 onUpgrade 方法的 SQliteDatabase,以及
      2. 从具有不同文件名的资产复制的 SQliteDatabase。
    2. ATTACH 将资产复制数据库(2.) 到传递的数据库(1.)

    3. 对传递的数据库进行准备性更改,例如删除表以及可能的索引和触发器。

    4. 将初始更改应用于传递的数据库,例如重新创建已删除的表。

    5. 根据需要填充更改的表(可能通过合适的插入/更新查询从资产副本数据库中提取数据并在传递的数据库中插入/更新新的/更改的表)。

    6. 应用最终更改,例如创建索引和触发器到传递的数据库 7. 将索引留到最后会更有效率。 7. 你可能不希望触发器触发,因此它们可能应该留到最后。

    7. DETACH 资产副本数据库

    8. 使用 File 的 delete 方法删除资产副本数据库。

    • 以上仅为粗略指导,根据要求,可能会有偏差。
    • 同样,取决于要求,例如如果您想基本上删除所有项目定义的表,然后从资产副本中添加所有表,那么您可以通过询问适当的 sqlite_master 来自动执行此操作(传递给删除现有表,以及资产副本的 sqlite_master 来创建和填充替换表)。
      • 虽然对于 Room 的内容类似于 answer 中的 PrepackagedDatabaseCallback 方法中所做的事情 (除了 CREATE .... 语句已被硬编码,它们必须是它们可能的样子从资产副本的 sqlite_master 中提取)

    【讨论】:

      猜你喜欢
      • 2020-11-03
      • 1970-01-01
      • 1970-01-01
      • 2020-09-14
      • 2013-08-09
      • 2018-04-30
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      相关资源
      最近更新 更多