如何在预先填充的数据库中使用Room Persistence Library?

时间:2017-05-30 13:38:53

标签: android android-sqlite android-room

我想将Room与预先填充的数据库一起使用,但我无法理解如何告诉Room在哪里可以找到我的数据库。

我现在把它放在src/main/assets/databases中,当我为Room数据库创建实例时,我就这样创建它:

Room.databaseBuilder(
    getApplicationContext(),
    AppDatabase.class,
    "justintrain.db"
)
.allowMainThreadQueries()
.build();

这样,我认为它每次创建一个新的数据库,或者不管怎样,它都没有使用预先填充的数据库。

如何才能找到我的数据库?

8 个答案:

答案 0 :(得分:34)

这就是我解决它的方法,以及如何使用预先填充的数据库发送您的应用程序(最多可达Room v.alpha5)

  • 将您的SQLite数据库database_name.db放入assets/databases文件夹

  • 获取文件from this repo并将其放入名为sqlAsset

  • 的包中 在您的AppDatabase课程中
  • ,相应地修改会议室的数据库创建代码:

    Room.databaseBuilder(context.getApplicationContext(), 
                         AppDatabase.class, 
                         "database_name.db")
    .openHelperFactory(new AssetSQLiteOpenHelperFactory())
    .allowMainThreadQueries()
    .build();
    

请注意,您必须使用"database_name.db"而不是getDatabasePath()或其他方法:它只需要文件名。

答案 1 :(得分:16)

我遇到了同样的问题所以我创建了一个完全正确的库。 接受的答案工作,但我认为使用图书馆更容易。

AppDatabase db = RoomAsset
    .databaseBuilder(context.getApplicationContext(), AppDatabase.class, "database_name.db")
    .build(); 

将其添加到存储库末尾的根build.gradle:

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

添加依赖项

dependencies {
    // ... other dependencies
    implementation 'com.github.humazed:RoomAsset:v1.0'
}

您可以在此处找到图书馆:https://github.com/humazed/RoomAsset

答案 2 :(得分:16)

没有任何其他外部库的简单解决方案。

Room依赖于现有的Android框架代码来创建或打开数据库。如果您查看FrameworkSQLiteOpenHelper(会议室版SQLiteOpenHelper)的源代码,则会在内部调用SQLiteOpenHelper.getReadableDatabase()以及其他需要的方法。

因此,最简单的解决方案是在创建具有Room的数据库之前,将数据库文件从assets目录复制到mContext.getDatabasePath("my-database.sqlite")

在您的情况下,代码看起来像这样 -

private final String DB_NAME = "my-database.sqlite";

private MyDatabase buildDatabase(Context context) {
    final File dbFile = context.getDatabasePath(DB_NAME);

    if(!dbFile.exists()) {
        copyDatabaseFile(dbFile.getAbsolutePath());
    }

    return Room.databaseBuilder(context.getApplicationContext(),
        MyDatabase.class, DB_NAME)
        .build();
}

private void copyDatabaseFile(String destinationPath) {
    // code to copy the file from assets/database directory to destinationPath
}

此链接包含复制数据库所需的代码 - link with code

答案 3 :(得分:7)

没有黑客或依赖关系的有效2019解决方案(Kotlin)

  1. 将您的.db文件放置在assets/databases(或实际上在其中的任何文件夹,只要它在assets下)。

  2. 使用Room 2.2现有的createFromAsset()函数,将其传递到数据库的路径。例如,如果您的数据库文件名为my_data.db,并且位于databases文件夹的assets目录下,那么您将执行createFromAsset("databases/my_data.db")

假设您的数据库名称(例如my_data)存储在名为DATABASE_NAME的常量变量中,则可以使用以下示例代码:

Room.databaseBuilder(
                    context.applicationContext,
                    MyDatabase::class.java,
                    DATABASE_NAME
                )
                    .createFromAsset("databases/$DATABASE_NAME.db")
                    .build()

重要:确保数据类/实体的架构与.db文件的架构完全匹配。例如,如果在NOT NULL文件中未将列明确标记为.db,则意味着该列可以为null 值。在Kotlin中,您必须将其与数据类中的val colName: dataType? = null相匹配。如果您只是进行val colName: dataType,则Kotlin会将其编译为NOT NULL列,并且在您尝试运行应用程序时会抛出异常。

注意:如果您想通过下载到Android设备本身的数据库文件创建Room数据库,则可以选择使用createFromFile()函数。查看official documentation上的操作方法。

答案 4 :(得分:3)

Room现在支持预先填充的数据库,只需使用诸如SQLite Browser之类的任何程序来准备数据库。然后将其放在Assets Folder的子文件夹database中,然后调用:

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromAsset("database/myapp.db")
.build()

如果您没有将数据库作为资产提供,而是下载了它或者它位于文件系统中,则该方法为:

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromFile(File("mypath"))
.build()

有关此功能的更多说明或数据库迁移,您可以检查Documentation Training

答案 5 :(得分:1)

从Room 2.2开始,您可以使用以下命令预先填充数据库:

Room.databaseBuilder(appContext, TestDatabase.class, “Sample.db”)
    .createFromAsset(“database/myapp.db”)
    .build()

答案 6 :(得分:0)

您只需将assets/databases复制到app/databases
而不是在addMigrations()中添加databaseBuilder 它会保留您的数据

答案 7 :(得分:0)

具有空间的类似解决方案,无需使用外部库: 1.将数据库复制到资产文件夹中 2.从资产文件夹复制数据库

public class MainActivity extends AppCompatActivity {

public static AppDatabase db;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    copyDatabase(getApplicationContext(), "yourdatabase.db");

    db = Room.databaseBuilder(getApplicationContext(), .class, "yourdatabase.db").allowMainThreadQueries().build();
}

private void copyDatabase(Context context, String databaseName) {
    final File dbPath = context.getDatabasePath(databaseName);

    // If the database already exists, return
    if (dbPath.exists()) {
        Log.d("Activity", "db Path Exists");
        return;
    }

    // Make sure we have a path to the file
    dbPath.getParentFile().mkdirs();

    // Try to copy database file
    try {
        final InputStream inputStream = context.getAssets().open(databaseName);
        final OutputStream output = new FileOutputStream(dbPath);

        byte[] buffer = new byte[8192];
        int length;

        while ((length = inputStream.read(buffer, 0, 8192)) > 0) {
            output.write(buffer, 0, length);
        }

        output.flush();
        output.close();
        inputStream.close();
    }
    catch (IOException e) {
        Log.d("Activity", "Failed to open file", e);
        e.printStackTrace();
    }
}

}