假设我有一个简单的Room数据库:
@Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
现在,我要添加一个新实体:Pet
并将版本增加到2:
@Database(entities = {User.class, Pet.class}, version = 2)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
当然,Room会引发异常: java.lang.IllegalStateException: A migration from 1 to 2 is necessary.
假设我没有更改User
类(因此所有数据都是安全的),我必须提供仅创建一个新表的迁移。因此,我正在研究Room生成的类,搜索生成的查询以创建我的新表,将其复制并粘贴到迁移中:
final Migration MIGRATION_1_2 =
new Migration(1, 2) {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `Pet` (`name` TEXT NOT NULL, PRIMARY KEY(`name`))");
}
};
但是,我发现手动进行操作很不方便。有没有办法告诉Room: 我没有触摸任何现有表,因此数据是安全的。 请为我创建迁移?
房 确实 不 具备良好的迁移系统,至少直到2.1.0-alpha03
。
因此,在我们拥有更好的迁移系统之前,有一些变通办法可以在会议室中轻松进行迁移。
由于不存在这样的方法,@Database(createNewTables = true)
或者MigrationSystem.createTable(User::class)
,它应该有一个或另一个,唯一可能的方法是在运行
CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))
在您的migrate
方法中。
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))")
}
}
为了获得以上 SQL 脚本,您有四种方法
基本上,您必须编写与Room生成的脚本匹配的上述脚本。这种方式是可行的,是不可行的。(考虑您有50个字段)
如果您exportSchema = true
在@Database
批注中加入,Room将在项目文件夹的/ schemas中生成数据库架构。用法是
@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
//...
}
确保您已在build.grade
应用模块中包含以下行
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
当您运行或构建项目时,您将获得一个JSON文件2.json
,其中包含Room数据库中的所有查询。
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "325bd539353db508c5248423a1c88c03",
"entities": [
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
因此,您可以createSql
在您的migrate
方法中包括以上内容。
如果您不想导出架构,则仍然可以通过运行或构建将生成AppDatabase_Impl.java
文件的项目来获取查询。并在指定文件内。
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
在createAllTables
方法内,将存在所有实体的创建脚本。您可以获取它并将其包含在您的migrate
方法中。
您可能会猜到,Room会在编译时间内并使用您添加的Annotation Processing
生成上述所有文件schema
和AppDatabase_Impl
文件。
kapt "androidx.room:room-compiler:$room_version"
这意味着您也可以这样做,并创建自己的注释处理库,该库将为您生成所有必要的创建查询。
这个想法是为@Entity
和的房间注释创建一个注释处理库@Database
。以带有注释的类@Entity
为例。这些是您必须遵循的步骤
StringBuilder
并追加“如果不存在则创建表”class.simplename
或按的tableName
字段获取表名称@Entity
。将其添加到您的StringBuilder
@ColumnInfo
注释来获取字段的名称,类型和可空性。对于每个字段,您都必须在中添加id INTEGER NOT NULL
列的样式StringBuilder
。@PrimaryKey
ForeignKey
,Indices
如果存在。完成后,将其转换为字符串并将其保存在您要使用的一些新类中。例如,将其保存如下
public final class UserSqlUtils {
public String createTable = “CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))”;
}
然后,您可以将其用作
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(UserSqlUtils().createTable)
}
}
我为自己创建了一个这样的库,您可以检出它,甚至可以在您的项目中使用它。请注意,我制作的库并不完整,只满足我创建表的要求。
RoomExtension可实现更好的迁移
使用RoomExtension的应用程序
希望它有用。
在撰写此答案时,会议室版本已定2.1.0-alpha03
,当我向开发人员发送电子邮件时,得到了答复
预计在
2.2.0
不幸的是,我们仍然缺乏更好的迁移系统。
然而,我发现手动操作很不方便。有没有办法告诉Room:我不会接触任何现有的表,所以数据是安全的。请为我创建迁移?
我需要在我的laravel项目中添加一个新列,这没有问题,我使用了进行了更新,一切正常。现在我需要找出这个表上有多少条记录,并用一些值进行更新。 我有表: 因此,我使用新的迁移文件创建了新字段: 现在我需要用一些值更新表中的这个字段,例如,如果表中有100条记录,那么我需要在每一行中插入值“carry-X”,其中X是一个从1到100的数字。例如: 逮捕令-1,逮捕令-2,......逮捕证-100
我有一些表,我想在这个表中添加新的列。我想添加默认值为空的字符串列。 我试着这样加上去 或 但我有一个错误
我在文件中的迁移中添加了一个新表。。 这是代码: 当我运行时,我的数据库中只有默认的laravel用户(和迁移)表。没有货币。 原因可能是什么? 编辑 迁移一切都很顺利。问题是: SQLSTATE[42000]:语法错误或访问冲突:1071指定的密钥太长;最大密钥长度为767字节(SQL:更改表用户添加唯一users_email_unique(电子邮件)) SQLSTATE[42000]:语法错误
问题内容: 我不知道如何使用Laravel框架向现有数据库表添加新列。 我试图使用…来编辑迁移文件。 在终端中,我执行和。 如何添加新列? 问题答案: 要创建迁移,您可以在Artisan CLI上使用migration:make命令。使用特定名称以避免与现有模型冲突 对于Laravel 3: 对于Laravel 5+: 然后,您需要使用该方法(在访问现有表而不是创建新表时)。您可以添加如下所示的列
我不知道如何使用Laravel框架将新列添加到现有的数据库表中。 我试图使用…编辑迁移文件。。。 在终端,我执行和。 如何添加新列?