我想将Room与预先填充的数据库一起使用,但我无法理解如何告诉Room在哪里可以找到我的数据库。
我现在把它放在src/main/assets/databases
中,当我为Room数据库创建实例时,我就这样创建它:
Room.databaseBuilder(
getApplicationContext(),
AppDatabase.class,
"justintrain.db"
)
.allowMainThreadQueries()
.build();
这样,我认为它每次创建一个新的数据库,或者不管怎样,它都没有使用预先填充的数据库。
如何才能找到我的数据库?
答案 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)
将您的.db
文件放置在assets/databases
(或实际上在其中的任何文件夹,只要它在assets
下)。
使用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();
}
}
}