我有一个包含数据的房间数据库,现在我想再增加一列。
房间版本2.4.0-alpha01及以上应该使自动迁移更容易,所以我这样使用它:
...
version = 2,
autoMigrations = {
@AutoMigration(from = 1, to = 2)
},
exportSchema = true
然后在我的模型类中,我添加了新的列名,并生成了它的setters和getters,就像其他的一样。
文件室文档指出,如果文件室由于复杂的模式更改而无法执行迁移,则会抛出编译时错误。然而,在我的例子中,我得到了一个关于预期模式和新模式(我在其中添加了一列)之间差异的运行时错误。
以下是错误:
java.lang.RuntimeException: Exception while computing database live data.
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.lang.IllegalStateException: Migration didn't properly handle: accounts(com.bisform.susu.models.Account).
Expected:
TableInfo{name='accounts', columns={accountSavings=Column{name='accountSavings', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountName=Column{name='accountName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateTime=Column{name='accountCreateTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfDeposits=Column{name='numberOfDeposits', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, accountNumber=Column{name='accountNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfWithdrawals=Column{name='numberOfWithdrawals', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, accountPayoutDate=Column{name='accountPayoutDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, phoneOfNextOfKin=Column{name='phoneOfNextOfKin', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountImageURI=Column{name='accountImageURI', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountID=Column{name='accountID', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, lastUpdatedDate=Column{name='lastUpdatedDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, phoneNumber=Column{name='phoneNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountPayoutTime=Column{name='accountPayoutTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, lastUpdatedTime=Column{name='lastUpdatedTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, nameOfNextOfKin=Column{name='nameOfNextOfKin', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateDate=Column{name='accountCreateDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, isPaidOut=Column{name='isPaidOut', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
E/AndroidRuntime: TableInfo{name='accounts', columns={accountSavings=Column{name='accountSavings', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountName=Column{name='accountName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateTime=Column{name='accountCreateTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfDeposits=Column{name='numberOfDeposits', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, accountNumber=Column{name='accountNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfWithdrawals=Column{name='numberOfWithdrawals', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, accountPayoutDate=Column{name='accountPayoutDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountImageURI=Column{name='accountImageURI', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountID=Column{name='accountID', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, lastUpdatedDate=Column{name='lastUpdatedDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, phoneNumber=Column{name='phoneNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountPayoutTime=Column{name='accountPayoutTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, lastUpdatedTime=Column{name='lastUpdatedTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateDate=Column{name='accountCreateDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, isPaidOut=Column{name='isPaidOut', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:103)
...
请问我应该如何处理此错误?如何使用当前提供的自动迁移功能获得正确迁移的空间?
解决上述问题所需要的只是清理项目和重建。我想旧的模式不知何故还在内存中,因此崩溃了。
请问我应该如何处理此错误?如何使用当前提供的自动迁移功能获得正确迁移的空间?
我相信只有在忽略自动迁移的情况下,您才会得到这个结果。对于您展示的代码,我认为唯一的方法是包括手动迁移,因为这将覆盖自动迁移。
如下所示的测试表明了这一点。
测试
此测试显示覆盖从V1到V2的自动迁移的效果,以及未覆盖时迁移的工作方式。
该测试基于根据预期(v2)和发现(v1)消息构建的Accounts类。
因此Accounts类是:-
@Entity(tableName = "accounts")
class Accounts {
//String phoneOfNextOfKin; //<<<<< For V2 else commented out
//String nameOfNextOfKin; //<<<<< for V2 else commented out
String accountSavings;
String accountName;
String accountCreateTime;
Integer numberOfDeposits;
String accountNumber;
int numberOfWithdrawals;
String accountPayoutDate;
String accountImageURI;
@PrimaryKey
Long accountId;
String lastUpdatedDate;
String phoneNumber;
String accountPayoutTime;
String lastUpdatedTime;
String accountCreateDate;
boolean isPaidOut;
}
在版本之间不会更改的@Dao类:-
@Dao
abstract class AccountsDao {
@Insert
abstract long insert(Accounts accounts);
@Query("SELECT * FROM accounts")
abstract List<Accounts> getAllFromAccounts();
}
@Database类:-
@Database(
entities = {Accounts.class},
version = TheDatabase.DBVERSION
/* following line, if no schema saved, needs to be commented out */
, autoMigrations = {@AutoMigration(from = 1, to = 2)}
)
abstract class TheDatabase extends RoomDatabase {
abstract AccountsDao getAccountsDao();
public static final int DBVERSION = 1; //<<<<< change accordingly
private static volatile TheDatabase instance = null;
static TheDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(
context,
TheDatabase.class,
"accounts.db"
)
.allowMainThreadQueries() //run on main thread for brevity and convenience
.addMigrations(MIGRATION_1_2) //<<<<< if included then Migration didn't properly handle:
.build();
}
return instance;
}
/* Only needed for creating error shown in question */
/* doesn't hurt if no addMigrations or when creating V1 */
static final Migration MIGRATION_1_2 = new Migration(1,2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
}
};
}
最后,开展下列活动:-
public class MainActivity extends AppCompatActivity {
TheDatabase db;
AccountsDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = TheDatabase.getInstance(this);
dao = db.getAccountsDao();
Accounts a = new Accounts();
a.accountCreateDate = "2021-01-01";
a.accountCreateTime = "08:00:00";
a.accountImageURI = "imageURI";
a.accountName = "MyAccount";
a.accountNumber = "0000000000";
a.accountPayoutDate = "2021-05-05";
a.accountPayoutTime = "10:00:00";
a.accountSavings = "savings";
a.lastUpdatedDate = "2021-05-03";
a.lastUpdatedTime = "09:15:00";
a.numberOfDeposits = 10;
a.numberOfWithdrawals = 5;
a.isPaidOut = false;
//a.nameOfNextOfKin = "Mr Next of Kin"; //<<<<< For V2
//a.phoneOfNextOfKin = "1111111111"; //<<<<< For V2
dao.insert(a);
for(Accounts account: dao.getAllFromAccounts()) {
String msg = "Account is " + account.accountName + " ID is " + account.accountId;
if (TheDatabase.DBVERSION > 1) {
//msg = msg + " next of kin is " + account.nameOfNextOfKin; //<<<<< For V2
}
Log.d("ACCOUNTINFO", msg);
}
}
}
运行和结果:-
>
应用程序成功运行,数据库检查器显示:-
架构和单行一样是预期的。
3.为转到V2所做的更改:-
>
在数据库DBVERSION从1更改为2和. addMigrations保留包括
在调用活动中,名称和近亲值被赋值,而不是被注释掉。msg变量被连接以包括近亲。
应用程序崩溃
:-
Caused by: java.lang.IllegalStateException: Migration didn't properly handle: accounts(a.a.so69442030javaroomautomigrationsaddcolumns.Accounts).
Expected:
2021-10-05 14:31:50.669 30268-30268/a.a.so69442030javaroomautomigrationsaddcolumns E/AndroidRuntime: TableInfo{name='accounts', columns={accountSavings=Column{name='accountSavings', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountName=Column{name='accountName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateTime=Column{name='accountCreateTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfDeposits=Column{name='numberOfDeposits', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountNumber=Column{name='accountNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfWithdrawals=Column{name='numberOfWithdrawals', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, phoneOfNextOfKin=Column{name='phoneOfNextOfKin', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountPayoutDate=Column{name='accountPayoutDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountImageURI=Column{name='accountImageURI', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountId=Column{name='accountId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, lastUpdatedDate=Column{name='lastUpdatedDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, phoneNumber=Column{name='phoneNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountPayoutTime=Column{name='accountPayoutTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, nameOfNextOfKin=Column{name='nameOfNextOfKin', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, lastUpdatedTime=Column{name='lastUpdatedTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateDate=Column{name='accountCreateDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, isPaidOut=Column{name='isPaidOut', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
2021-10-05 14:31:50.670 30268-30268/a.a.so69442030javaroomautomigrationsaddcolumns E/AndroidRuntime: TableInfo{name='accounts', columns={accountSavings=Column{name='accountSavings', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountName=Column{name='accountName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateTime=Column{name='accountCreateTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfDeposits=Column{name='numberOfDeposits', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountNumber=Column{name='accountNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, numberOfWithdrawals=Column{name='numberOfWithdrawals', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, accountPayoutDate=Column{name='accountPayoutDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountImageURI=Column{name='accountImageURI', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountId=Column{name='accountId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, lastUpdatedDate=Column{name='lastUpdatedDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, phoneNumber=Column{name='phoneNumber', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountPayoutTime=Column{name='accountPayoutTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, lastUpdatedTime=Column{name='lastUpdatedTime', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, accountCreateDate=Column{name='accountCreateDate', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, isPaidOut=Column{name='isPaidOut', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:103)
步骤1-2在卸载应用程序并按照V1使用代码后重新运行(从头开始演示整个过程)(用注释掉或删除的. addMigrations重新运行将克服这个问题)
按照第3步进行的更改被应用,但是另外,数据库构建中的. addMigrations行被注释掉了。
并且我发现了基于数据库版本4的可能场景的迁移varargs。 我的问题是,假设我使用的是db v1的Room,当我的应用程序到达db v10时,我将不得不编写多少迁移方法? 在sqlite中,我们在中获得已安装应用程序的当前db版本,我们只需通过开关大小写而不使用break语句,以便满足所有db升级。
在构建Room数据库之前,我尝试保留旧的SqliteOpenHelper并使用它从1升级到3。这在第一次运行时有效,但随后的运行会使SqliteOpenHelper崩溃,因为它不能降级数据库(Room成功升级到v4,但open helper只知道v3。使用它来确保升级到v3的数据库会导致它尝试降级)
我在存钱 进入我的房间数据库版本1。 现在我需要将
已经创建了一个@Embedded类播放器。我想在其中添加ArrayList字段,该字段使用@TypeConverters,它在保存时将列表转换为Gson,在加载时将其转换为Gson。请告诉我如何在void migrate() 方法中请求将列表添加到Player类的现有实例中。 类保存: TypeConverter:
我转换java代码到kotlin代码,我得到类型未解决的java类错误。 我的Java类是 已转换的Kotlin类 非常感谢。
我正在使用2.4.0-ALPHA01房间