由区域设置依赖表名

时间:2018-03-22 16:23:58

标签: android sqlite android-sqlite database-migration ormlite

我的问题是如何以适用于现有Sqlite数据库(更新应用程序的用户)以及防止将来发生这种情况的方式解决我们遇到的问题。

问题 我们在Android应用程序中使用OrmLite,我们创建表格的方式是我们在模型上使用OrmLite注释@DatabaseTable

深入研究OrmLite源代码,发现DatabaseTableConfig.extractTableName方法可以获取表名,如果您没有将其指定为注释的参数

clazz.getSimpleName().toLowerCase()

查看String的源代码,发现它执行此操作

toLowerCase(Locale.getDefault())

对于某些调用toLowerCase()的语言实际上会更改表名(在本例中是类名)

例如,如果我们有一个名为info的表,则表名可以转换为ınfo

现在考虑这个场景

  • 用户手机上有非英语区域设置,表格是 创建它被称为ınfo
  • 用户将语言环境更改为英语
  • 用户升级应用程序,并调用onUpgrade,我们尝试ALTER 表info,但我们找不到它,因为它实际上被调用了 ınfo

想到的唯一解决方案

  • 强制所有用户使用toLowerCase(Locale.ENGLISH)
  • 当我们遇到无法找到关于升级的表格的情况时 删除该表并重新创建它

这有失去本地存储的用户信息的缺点

我的问题是,是否有人建议在我们不丢失旧数据的情况下向前/向后兼容?

注意:我不知道有多少语言环境会将英文字母改成其他内容,所以基本上我不知道哪个地方是旧的,可​​以尝试"猜测"旧表名称和从中迁移数据

1 个答案:

答案 0 :(得分:0)

我唯一能想到的就是使用这样的查询:

"SELECT name FROM sqlite_master WHERE type = 'table'"

获取DB中的所有表名。

您可以在用户db的某种更新/重建实用程序中使用它,并尝试将英语区域设置中的表名与表名集内的内容进行匹配。

找到匹配后,您可以使用例如:

来修复名称
"ALTER TABLE old_name RENAME TO new_name"

很难给出一些匹配方法的直接想法,但你可以检查:

("ınfo".toUpperCase(Locale.ENGLISH)).toLowerCase(Locale.ENGLISH).equals("info")

这个“ı”字符问题是众所周知的,例如在使用土耳其语语言环境时,据我所知

"ı".toUpperCase(Locale.ENGLISH).equals("I") 

"I".toLowerCase(Locale.ENGLISH).equals("i")

所以我发布了这次双重转换的机会。