我有一个db.sqlite
转储文件。当我在SQLite Browser中查看它时,我可以看到它包含许多CREATE TABLE, CREATE INDEX
语句。我使用这个转储文件通过createFromAsset("db.sqlite")
函数创建我的房间数据库。
我的问题是,将这些表中的数据类型从转储文件Map到Room实体中的Kotlin数据类型的正确方法是什么?从SQLite转储文件到Room实体的数据类型Map是否有规则?有没有一个自动化的工具/库可以为我做这件事?
SQLite Browser在这些表中显示的类型非常广泛:
date, datetime, mediumtext, varchar(255), varchar(32), tinyint(1), int(1), int(10), bigint(20), TEXT
1条答案
按热度按时间5uzkadbs1#
有没有一个自动化的工具/库可以为我做这件事?
不(我知道)。我确实有一个,但随着房间开始改变/增加功能,它成为一个噩梦,它并不是很难转换。如下文所示,Room可以帮助您并使您的生活更轻松。
我的问题是,将这些表中的数据类型从转储文件Map到Room实体中的Kotlin数据类型的正确方法是什么?从SQLite转储文件到Room实体的数据类型Map是否有规则?
列类型为INTEGER、TEXT、BLOB或真实的四种类型之一。只能使用这些类型。但是,当Room查看
@Entity
注解类中的字段时,Room将根据类型生成这些字段。*房间不符合默认/通过
NUMERIC
类型下降,它不能使用,必须转换。1.字符串将转换为TEXT。
1.整数类型(例如
Long
,Int
,Byte
....)将转换为INTEGER。1.十进制类型(例如
Double
,Float
....)将转换为真实的1.一个字节流,例如
ByteArray
,将被转换为BLOB1.更复杂的对象(例如,Date)必须转换为基本类型或String(通常后者作为JSON表示),或者可以添加组成对象的字段(可能通过
@Embedded
注解)1.通过基本的原始类型,这并不意味着按照Java int,long等实际的原始类型,而是Room知道的类型将是上面四种列类型之一。
现在考虑
date, datetime, mediumtext, varchar(255), varchar(32), tinyint(1), int(1), int(10), bigint(20), TEXT
String
或Long
。var mydate: Date
然后你需要一个TypeConverter将日期转换为Long/Int或String(如果需要,甚至是ByteArray)。String
String
Long
或Int
现在,您可能遇到的真实的问题是,如果使用createFromAsset,您将需要转换资产。
最简单的方法是首先创建
@Entity
注解的类,每个表一个,基于上面的内容,即决定实际存储什么类型的数据,因为SQLite中的列名非常灵活,而且您可以在任何列中存储任何类型(上面的例外),因此实际数据可能很重要。当您对建议的实体进行编码时,然后用entities参数指定
@Entity
注解的类来编码@Database
注解的类。它可以像这样简单,例如:@Entity
注解的类可能不是Entity
和Entity2
*现在编译项目(成功)。
然后,Room将生成包含用于创建表的SQL的java。
上面的示例(基于对各种类型的假设近似):-
Entity1 for want of better names:-
@Database
注解类:-编译成功
例如:-
在Android View中,
1.找到
java(generated)
,然后1.与
@Database
注解类同名的类,后缀为Impl,然后1.方法名createAllTables
例如:-
从上面的
createAllTables
方法是:可以看出,Room转换类型如上所述但是注意,Room做了更多的事情,例如添加NOT NULL约束,或者不像
varchar255
列那样。@ColumnInfo(defaultValue = "whaetever")
,则将使用DEFAULT 'whaetever'
)DEFAULT ....
,这可能会使数据的复制复杂化(下面的步骤3)。Room将只接受具有根据生成的SQL定义的数据库。如果存在任何差异,则结果将是一个例外,即列出房间预期和发现。
因此,毫无疑问,从资产复制的数据库需要更改(列表中唯一可接受的列类型是TEXT,其他任何列类型都会导致异常)。
您可以在将数据库复制到assets文件夹之前对其进行转换,也可以使用
PrepackagedDatabaseCallback
,其使用示例可以在此处找到How do I use Room's prepackagedDatabaseCallback?我相信使用SQLiteBrowser这样的工具更容易,在这种情况下,您可以基于以下转换:
1.使用
ALTER TABLE
重命名原始表。1.使用上面获得的生成的SQL创建表。
1.不需要麻烦room_master_table,room会处理。
1.将重命名的原始表中的数据复制到它们的等效表中
1.可以像
INSERT INTO entity1 SELECT * FROM renamed_entity1
一样简单,也可以更复杂,例如如果NOT NULL的值为null(可能会将?
添加到字段中,重新编译等)1.使用
DROP TABLE ....
删除重命名的表1.也许可以考虑做一个
VACUUM
1.保存数据库,然后将其复制到assets文件夹中
1.然后可以完成Room代码(添加
@Dao
注解的接口,修改@Database
注解的类,根据需要添加POJO)。如果一切都做得很好,那么数据库应该被打开并成功使用。