有SQLiteOpenHelper
一种onCreate(SQLiteDatabase ...)
方法,我用来用一些初始数据填充数据库表。
有没有办法在第一次运行应用程序时将一些数据插入到 Room 数据库表中?
有SQLiteOpenHelper
一种onCreate(SQLiteDatabase ...)
方法,我用来用一些初始数据填充数据库表。
有没有办法在第一次运行应用程序时将一些数据插入到 Room 数据库表中?
更新
您可以通过 3 种方式执行此操作:重要检查此以获取迁移详细信息
1-从导出的资产模式填充您的数据库
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromAsset("database/myapp.db")
.build();
2-从文件填充您的数据库
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromFile(new File("mypath"))
.build();
3-您可以在创建数据库后运行脚本或每次使用打开数据库时运行脚本RoomDatabase.Callback
,此类在最新版本的 Room 库中可用。
您需要实现onCreate
和onOpen
方法RoomDatabase.Callback
并将其添加到RoomDatabase.Builder
如下所示。
yourDatabase = Room.databaseBuilder(context, YourDatabase.class, "your db")
.addCallback(rdc)
.build();
RoomDatabase.Callback rdc = new RoomDatabase.Callback() {
public void onCreate (SupportSQLiteDatabase db) {
// do something after database has been created
}
public void onOpen (SupportSQLiteDatabase db) {
// do something every time database is open
}
};
您可以在 RoomDatabase.Callback 方法中使用 Room DAO 本身来填充数据库。有关完整示例,请参阅分页和房间示例
RoomDatabase.Callback dbCallback = new RoomDatabase.Callback() {
public void onCreate(SupportSQLiteDatabase db) {
Executors.newSingleThreadScheduledExecutor().execute(new Runnable() {
@Override
public void run() {
getYourDB(ctx).yourDAO().insertData(yourDataList);
}
});
}
};
我尝试按照 Arnav Rao 的建议使用 RoomDatabase.Callback,但要使用回调,您不能使用 DAO,因为回调是在构建数据库之前创建的。您可以使用 db.insert 和 content 值,但我认为这不正确。因此,在对其进行了更多研究之后——花了我很多时间哈哈——但实际上我在浏览谷歌提供的样本时找到了答案。
请参见第 52 行和第 71 行的方法 - 在那里您可以看到在构建数据库实例之后,下一行调用一个方法,该方法检查数据库中是否有任何记录(使用 DAO),然后它是否为空插入初始数据(再次使用 DAO)。
希望这可以帮助其他陷入困境的人:)
您可以在创建数据库后填充表,确保操作在单独的线程上运行。您可以按照以下课程第一次预先填充表格。
应用数据库.kt
@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
// For Singleton instantiation
@Volatile private var instance: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
return instance ?: synchronized(this) {
instance ?: buildDatabase(context).also { instance = it }
}
}
private fun buildDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
//pre-populate data
Executors.newSingleThreadExecutor().execute {
instance?.let {
it.userDao().insertUsers(DataGenerator.getUsers())
}
}
}
})
.build()
}
}
}
数据生成器.kt
class DataGenerator {
companion object {
fun getUsers(): List<User>{
return listOf(
User(1, "Noman"),
User(2, "Aayan"),
User(3, "Tariqul")
)
}
}
}
我尝试了多种方法来做到这一点,每一种都没有。
首先,我尝试使用“addMigrations”方法将迁移实现添加到 Room,但发现它仅在数据库升级期间运行,而不是在创建时运行。
然后,我尝试使用“openHelperFactory”方法将 SQLiteOpenHelper 实现传递给 Room。但是在创建了一堆类以绕过 Room 的包级访问修饰符之后,我放弃了努力。我还尝试对 Room 的 FrameworkSQLiteOpenHelperFactory 进行子类化,但同样,它的构造函数的包级访问修饰符不支持这一点。
最后,我创建了一个 IntentService 来填充数据并从我的 Application 子类的 onCreate 方法调用它。该方法有效,但更好的解决方案应该是即将修复本页其他地方 Sinigami 提到的跟踪器问题。
达里尔
[2017 年 7 月 19 日添加]
该问题似乎已在 Room 1.0.0 中解决。Alpha 5。此版本向 RoomDatabase 添加了一个回调,允许您在首次创建数据库时执行代码。看一眼:
https://developer.android.com/reference/android/arch/persistence/room/RoomDatabase.Callback.html
@Provides
@Singleton
LocalDatabase provideLocalDatabase(@DatabaseInfo String dbName, Context context) {
return Room.databaseBuilder(context, LocalDatabase.class, dbName)
.addCallback(new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
db.execSQL("INSERT INTO id_generator VALUES(1, 1, 1);");
}
})
// .addMigrations(LocalDatabase.MIGRATION_1_2)
.build();
}
有3 种预填充 db
的方法第 2 种是从这里
描述
的资产和文件处理第三种方法是在创建 db 后编程
Room.databaseBuilder(context, Database::class.java, "app.db")
// ...
// 1
.createFromAsset(...)
// 2
.createFromFile(...)
// 3
.addCallback(DatabaseCallback())
.build()
这是手动填充
class DatabaseCallback : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) = db.run {
// Notice non-ui thread is here
beginTransaction()
try {
execSQL(...)
insert(...)
update(...)
delete(...)
setTransactionSuccessful()
} finally {
endTransaction()
}
}
}
我也在为这个话题而苦苦挣扎,这个解决方案对我有用:
// build.gradle
def room_version = "2.2.5"
// Room
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
在您的 App 类中:
// virtually create the db
val db = Room.databaseBuilder(
appContext, AppDatabase::class.java,
Res.getString(R.string.dbname)
).createFromAsset(Res.getString(R.string.source_db_name)).build()
// first call to db really creates the db on filesystem
db.query("SELECT * FROM " + Room.MASTER_TABLE_NAME, null)