迁移房间数据库时有没有办法使用迁移期间计算的变量?
Posted
技术标签:
【中文标题】迁移房间数据库时有没有办法使用迁移期间计算的变量?【英文标题】:Is there a way when Migrating a Room Database to use Variables that are calculated during the Migration? 【发布时间】:2021-06-17 00:26:30 【问题描述】:我正在用 Java 编写一个 android 应用程序,并且我已经更改了我的数据库,现在我想将它迁移到新版本,但为此我需要计算一些旧值,然后将它们插入其中一个新表进入数据库但是当我调用时
database.execSQL()
使用我的变量然后访问它们似乎没有设置它们,因为每个值都是 0。
这是不可能的,还是我只是错过了什么?
public void migrate(@NonNull SupportSQLiteDatabase database)
database.execSQL("CREATE TABLE 'season' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
'spring' INTEGER DEFAULT 0, 'summer' INTEGER DEFAULT 0, 'autumn' INTEGER
DEFAULT 0, 'winter'
INTEGER DEFAULT 0, 'spook' INTEGER DEFAULT 0)");
database.execSQL("INSERT INTO 'Clothes' (type_of_clothing,clothing_name,description,seasonId,in_laundry,TypeList) " +
"SELECT type_of_clothing,clothing_name,description,type_of_clothing,in_laundry,TypeList " +
"FROM ClothesNew");
Cursor cursor = database.query("SELECT * FROM Clothes");
Cursor secondCursor = database.query("SELECT * FROM ClothesSeason");
ArrayList<Season> seasonsToBeAdded = new ArrayList<>();
while (cursor.moveToNext())
secondCursor.moveToNext();
int Sid = cursor.getInt(0);
String seasonString = secondCursor.getString(2);
Season season = new Season(seasonString);
int tempId = Sid;
boolean isInList = false;
for (Season tempSeason : seasonsToBeAdded)
if (tempSeason.equals(season))
tempId = seasonsToBeAdded.indexOf(tempSeason);
isInList = true;
break;
if (!isInList)
season.setId(seasonsToBeAdded.size());
tempId = season.getId();
seasonsToBeAdded.add(season);
if (seasonsToBeAdded.size() == 0) seasonsToBeAdded.add(season);
database.execSQL("UPDATE Clothes SET seasonId = :tempId WHERE uid = :Sid");
int id, spring, summer, autumn, winter, spook;
for (Season season : seasonsToBeAdded)
id = season.getId();
spring = season.getSpring();
summer = season.getSummer();
autumn = season.getAutumn();
winter = season.getWinter();
spook = season.getSpook();
database.execSQL("INSERT INTO season " +
"VALUES(:id, :spring, :summer, :autumn, :winter, :spook) ");
Cursor otherCursor = database.query("SELECT * FROM season");
ArrayList<Integer> springValues= new ArrayList<>();
while (otherCursor.moveToNext())
springValues.add(otherCursor.getInt(1));
当我查看存储在 springValues 中的值时,即使我在此查询中添加了正确的值,它们也都是 0
database.execSQL("INSERT INTO season " +
"VALUES(:id, :spring, :summer, :autumn, :winter, :spook) ");
我可以不在这里使用 :var 符号吗?
【问题讨论】:
【参考方案1】:我建议使用 SQLiteDatabase
Insert
便捷方法和 ContentValues
对象。
而不是:-
for (Season season : seasonsToBeAdded)
id = season.getId();
spring = season.getSpring();
summer = season.getSummer();
autumn = season.getAutumn();
winter = season.getWinter();
spook = season.getSpook();
database.execSQL("INSERT INTO season " +
"VALUES(:id, :spring, :summer, :autumn, :winter, :spook) ");
您的代码可能是:-
ContentValues cv = new ContentValues(); // Instantiate ContentValues object
for (Season season : seasonsToBeAdded)
cv.clear();
cv.put("`id`",season.getId());
cv.put("`spring`",season.getSpring());
cv.put("`summer`",season.getSummer());
cv.put("`autumn`",season.getAutumn());
cv.put("`winter`",season.getWinter());
cv.put("`spook`",season.getSpook());
database.insert("season",null,cv); //<<<< Recommended Uses the convenience Insert Method
请注意,列名不必像上面使用的那样用重音 `` 括起来。
以上代码为in-principal code,未经测试,可能存在一些错误。
如您所见,SQL 是为您构建的。 insert
方法返回插入行的 rowid(id 列),如果插入失败则返回 -1,您可能希望利用该值。
您可能还希望使用其他插入方法,例如insertWithOnConflict 例如database.insertWithOnConflict("season",null,cv,SQLiteDatabase.CONFLICT_IGNORE);
还建议通过使用适当的 SQLiteDatabase 事务处理方法来利用事务(请参阅beginTransaction)
还建议您对列名使用常量,以便在适当的位置对名称进行编码。列名错误的可能性很小。
【讨论】:
以上是关于迁移房间数据库时有没有办法使用迁移期间计算的变量?的主要内容,如果未能解决你的问题,请参考以下文章