Migration Error: How to migrate Indices and Typeconverters?
Migration Error: How to migrate Indices and Typeconverters?
我有一个简单的驱动程序class:
@Entity(tableName = "Driver",
indices = {@Index(value = {"driverName"},unique = true), @Index(value = {"drivingLicNum"},unique = true)}
)
public class Driver {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
@NotNull
private int id;
@ColumnInfo(name = "firstName")
@NotNull
private String firstName;
@ColumnInfo(name = "lastName")
@NotNull
private String lastName;
@ColumnInfo(name = "driverName")
@NotNull
private String driverName;
//optionale Parameter
@ColumnInfo(name = "birthDate")
@TypeConverters(Converters.class)
private Date birthDate;
@ColumnInfo(name = "drivingLicNum")
private String drivingLicNum;
@ColumnInfo(name = "drivingLicExpDate")
@TypeConverters(Converters.class)
private Date drivingLicExpDate;
@ColumnInfo(name = "gender")
@TypeConverters(Converters.class)
private Gender gender;
@ColumnInfo(name = "issuingAuthority")
private String issuingAuthority;
@ColumnInfo(name = "licCategory")
@TypeConverters(Converters.class)
private ArrayList<LicenceCategory> licCategory;
@ColumnInfo(name = "isActive", defaultValue = "1")
@NotNull
private boolean isActive;
@ColumnInfo(name = "profilePic")
private byte[] profilePic;
public Driver(@NotNull String firstName, @NotNull String lastName, @NotNull String driverName) {
this.firstName = firstName;
this.lastName = lastName;
this.driverName = driverName;
licCategory = new ArrayList<>();
setIsActive(true);
}
}
我的TypeConverter
class:
public final class Converters {
private static Gson gson = new Gson();
@TypeConverter
public static ArrayList<LicenceCategory> fromStringToLicenceCategories(String value) {
Type listType = new TypeToken<ArrayList<LicenceCategory>>() {}.getType();
return gson.fromJson(value, listType);
}
@TypeConverter
public static String fromLicenceCategoriesToString(ArrayList<LicenceCategory> list) {
return gson.toJson(list);
}
@TypeConverter
public static Gender fromStringToGender(String value) {
Type listType = new TypeToken<Gender>() {}.getType();
return gson.fromJson(value, listType);
}
@TypeConverter
public static String fromGenderToString(Gender gender) {
return gson.toJson(gender);
}
@TypeConverter
public static Date fromTimestampToDate(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long fromDateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
最后但同样重要的是,我的数据库中的迁移代码 class:
@Database(entities = {Driver.class, User.class}, version = 2, exportSchema = false)
@TypeConverters({Converters.class})
public abstract class CarServiceDB extends RoomDatabase{
private static CarServiceDB instance;
public static CarServiceDB getDatabase(Context context) {
if (instance == null) {
Migration migration = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS Driver (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, firstName TEXT NOT NULL, " +
"lastName TEXT NOT NULL, driverName TEXT NOT NULL UNIQUE, birthDate NUMERIC, drivingLicNum INTEGER UNIQUE, drivingLicExpDate NUMERIC, " +
"gender TEXT CHECK(gender = \"MALE\" or gender = \"FEMALE\" or gender = \"UNKNOWN\"), " +
"issuingAuthority TEXT, licCategory TEXT, isActive INTEGER NOT NULL DEFAULT 1 CHECK(isActive IN (0,1)),profilePic BLOB)");
}
};
instance = Room.databaseBuilder(context, CarServiceDB.class, "mycardatabase.db").addMigrations(migration).createFromAsset("databases/mycardatabase.db").build();
}
return instance;
}
public abstract UserDao userDao();
}
但是我得到了可能是最烦人的 Room 异常错误之一:
我用黄色标记了不匹配的列。正如您所看到的,Date TypeConverter 没有正确迁移,即使我说日期的数据类型为 NUMERIC
并且出于某种原因,任何空间都会创建一个 indices column
,它不会迁移,即使我添加了 indices
注释我的 Driver
class。我错过了什么?
迁移可能是 ....
我尝试了您的代码并发现了问题:
Migration migration = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("DROP TABLE IF EXISTS Driver");
database.execSQL("CREATE TABLE IF NOT EXISTS Driver (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, firstName TEXT NOT NULL, " +
"lastName TEXT NOT NULL, driverName TEXT UNIQUE NOT NULL , birthDate INTEGER, drivingLicNum TEXT UNIQUE, drivingLicExpDate INTEGER, " +
"gender TEXT CHECK(gender = \"MALE\" or gender = \"FEMALE\" or gender = \"UNKNOWN\"), issuingAuthority TEXT, licCategory TEXT, isActive INTEGER NOT NULL DEFAULT 1 CHECK(isActive IN (0,1)),profilePic BLOB)");
database.execSQL("CREATE UNIQUE INDEX index_Driver_drivingLicNum ON Driver(drivingLicNum)");
database.execSQL("CREATE UNIQUE INDEX index_Driver_driverName ON Driver(driverName)");
}
我改变了什么?:
- 您需要为每个唯一列创建一个唯一索引
- 您需要将日期数据类型更改为 INTEGER 而不是 NUMERIC,因为 SQLLITE 需要 INTEGER。
我有一个简单的驱动程序class:
@Entity(tableName = "Driver",
indices = {@Index(value = {"driverName"},unique = true), @Index(value = {"drivingLicNum"},unique = true)}
)
public class Driver {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
@NotNull
private int id;
@ColumnInfo(name = "firstName")
@NotNull
private String firstName;
@ColumnInfo(name = "lastName")
@NotNull
private String lastName;
@ColumnInfo(name = "driverName")
@NotNull
private String driverName;
//optionale Parameter
@ColumnInfo(name = "birthDate")
@TypeConverters(Converters.class)
private Date birthDate;
@ColumnInfo(name = "drivingLicNum")
private String drivingLicNum;
@ColumnInfo(name = "drivingLicExpDate")
@TypeConverters(Converters.class)
private Date drivingLicExpDate;
@ColumnInfo(name = "gender")
@TypeConverters(Converters.class)
private Gender gender;
@ColumnInfo(name = "issuingAuthority")
private String issuingAuthority;
@ColumnInfo(name = "licCategory")
@TypeConverters(Converters.class)
private ArrayList<LicenceCategory> licCategory;
@ColumnInfo(name = "isActive", defaultValue = "1")
@NotNull
private boolean isActive;
@ColumnInfo(name = "profilePic")
private byte[] profilePic;
public Driver(@NotNull String firstName, @NotNull String lastName, @NotNull String driverName) {
this.firstName = firstName;
this.lastName = lastName;
this.driverName = driverName;
licCategory = new ArrayList<>();
setIsActive(true);
}
}
我的TypeConverter
class:
public final class Converters {
private static Gson gson = new Gson();
@TypeConverter
public static ArrayList<LicenceCategory> fromStringToLicenceCategories(String value) {
Type listType = new TypeToken<ArrayList<LicenceCategory>>() {}.getType();
return gson.fromJson(value, listType);
}
@TypeConverter
public static String fromLicenceCategoriesToString(ArrayList<LicenceCategory> list) {
return gson.toJson(list);
}
@TypeConverter
public static Gender fromStringToGender(String value) {
Type listType = new TypeToken<Gender>() {}.getType();
return gson.fromJson(value, listType);
}
@TypeConverter
public static String fromGenderToString(Gender gender) {
return gson.toJson(gender);
}
@TypeConverter
public static Date fromTimestampToDate(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long fromDateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
最后但同样重要的是,我的数据库中的迁移代码 class:
@Database(entities = {Driver.class, User.class}, version = 2, exportSchema = false)
@TypeConverters({Converters.class})
public abstract class CarServiceDB extends RoomDatabase{
private static CarServiceDB instance;
public static CarServiceDB getDatabase(Context context) {
if (instance == null) {
Migration migration = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS Driver (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, firstName TEXT NOT NULL, " +
"lastName TEXT NOT NULL, driverName TEXT NOT NULL UNIQUE, birthDate NUMERIC, drivingLicNum INTEGER UNIQUE, drivingLicExpDate NUMERIC, " +
"gender TEXT CHECK(gender = \"MALE\" or gender = \"FEMALE\" or gender = \"UNKNOWN\"), " +
"issuingAuthority TEXT, licCategory TEXT, isActive INTEGER NOT NULL DEFAULT 1 CHECK(isActive IN (0,1)),profilePic BLOB)");
}
};
instance = Room.databaseBuilder(context, CarServiceDB.class, "mycardatabase.db").addMigrations(migration).createFromAsset("databases/mycardatabase.db").build();
}
return instance;
}
public abstract UserDao userDao();
}
但是我得到了可能是最烦人的 Room 异常错误之一:
我用黄色标记了不匹配的列。正如您所看到的,Date TypeConverter 没有正确迁移,即使我说日期的数据类型为 NUMERIC
并且出于某种原因,任何空间都会创建一个 indices column
,它不会迁移,即使我添加了 indices
注释我的 Driver
class。我错过了什么?
迁移可能是 .... 我尝试了您的代码并发现了问题:
Migration migration = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("DROP TABLE IF EXISTS Driver");
database.execSQL("CREATE TABLE IF NOT EXISTS Driver (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, firstName TEXT NOT NULL, " +
"lastName TEXT NOT NULL, driverName TEXT UNIQUE NOT NULL , birthDate INTEGER, drivingLicNum TEXT UNIQUE, drivingLicExpDate INTEGER, " +
"gender TEXT CHECK(gender = \"MALE\" or gender = \"FEMALE\" or gender = \"UNKNOWN\"), issuingAuthority TEXT, licCategory TEXT, isActive INTEGER NOT NULL DEFAULT 1 CHECK(isActive IN (0,1)),profilePic BLOB)");
database.execSQL("CREATE UNIQUE INDEX index_Driver_drivingLicNum ON Driver(drivingLicNum)");
database.execSQL("CREATE UNIQUE INDEX index_Driver_driverName ON Driver(driverName)");
}
我改变了什么?:
- 您需要为每个唯一列创建一个唯一索引
- 您需要将日期数据类型更改为 INTEGER 而不是 NUMERIC,因为 SQLLITE 需要 INTEGER。