持久化库查询中的COLLATE LOCALIZED无法工作

8
我正在使用今年Google I/O发布的新Room持久化库,目前效果非常好,但是无法按照UNICODELOCALIZED对结果进行排序。唯一有效的是NOCASE,但在我的情况下是无用的。

是否有任何方法可以实现此功能?

@Dao
public interface ContactDao { 

    @Query("SELECT * FROM contact ORDER BY lastName COLLATE LOCALIZED")
    Flowable<List<Contact>> getAll();
}

如果我按照上面的方式构建查询,就会出现错误:
Error:(21, 29) error: There is a problem with the query: [SQLITE_ERROR] 
SQL error or missing database (no such collation sequence: LOCALIZED)

如果我理解正确,要使用COLLATE LOCALIZED,您需要在CREATE TABLE语句中声明它作为列约束的一部分。似乎您可以使用“迁移”来编写自己的“CREATE TABLE”语句,但我不清楚如何为初始表格创建“迁移”(而不是升级)。我不知道是否是您提交了[此问题](https://issuetracker.google.com/issues/62007004),但我会密切关注它。 - CommonsWare
嗨,你修好了吗? - José Carlos
不是很...目前我只是在使用列表之前对其进行排序。Collections.sort(nameOfYourList) { o1, o2 -> Collator.getInstance(Locale.GERMAN).compare(o1.lastName, o2.lastName) } - denwehrle
3个回答

8
你必须使用这些房间版本。
compile "android.arch.persistence.room:runtime:1.1.1"
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"

更新了您的房间 Gradle 行之后,
您可以使用此功能:
@ColumnInfo(collate = ColumnInfo.NOCASE)

是的!这个问题很老了,但在更新的版本中,这个功能终于被实现了。 - denwehrle
1
@ColumnInfo(collate = ColumnInfo.NOCASE): - live-love

1

我不知道为什么LOCALIZED排序(在Room版本1.0.0中)没有被实现,而在文档中有提到(https://developer.android.com/reference/android/arch/persistence/room/ColumnInfo.html#LOCALIZED)。我发现了这个问题报告https://issuetracker.google.com/issues/68925249,它被标记为已解决 - 但可能尚未发布。

因此,像CommonsWare在问题中评论的那样,有一个丑陋的解决方法 - 在CREATE语句中定义它。这可以通过数据库构建器中的回调来实现。但是存在一个问题 - 我们必须使用create table,因为sqlite不支持alter collate。而且因为表在回调中已经存在,所以我们必须删除这个表。

这是我的实现(用Kotlin编写) - create语句必须同时复制实体类定义和索引:

@Database(entities = [(LocalityItem::class)], version = AppDatabase.DB_VERSION, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {

    abstract fun localityDao(): LocalityDao

    companion object {
        const val DB_NAME : String = "app_db"
        const val DB_VERSION : Int = 1

        private var INSTANCE: AppDatabase? = null

        private val CALLBACK: Callback = object : Callback() {
            override fun onCreate(db: SupportSQLiteDatabase) {
                db.execSQL("DROP TABLE `locality` ")
                db.execSQL("CREATE TABLE `locality` ("
                        + " `id` INTEGER,"
                        + " `type` INTEGER,"
                        + " `name` TEXT COLLATE LOCALIZED, "
                        + " `row_index` INTEGER,"
                        + " `col_index` INTEGER,"
                        + " PRIMARY KEY(`id`)"
                        + ")")
                db.execSQL("CREATE INDEX `index_locality_type` ON `locality` (`type`)")
                db.execSQL("CREATE INDEX `index_locality_name` ON `locality` (`name`)")
            }
        }

        fun getInstance(context : Context) : AppDatabase? {
            if (INSTANCE == null) {
                synchronized(AppDatabase::class) {
                    INSTANCE = Room.databaseBuilder(
                            context.applicationContext,
                            AppDatabase::class.java, DB_NAME)
                            .addCallback(CALLBACK)
                            .build()
                }
            }
            return INSTANCE
        }
    }
}

-2

使用以下方式在列定义时使用COLLATE,

@ColumnInfo(collate = NOCASE) var name: String

对我来说它运行良好。 无需在Query中指定COLLATE

Room中也没有LOCALIZED排序规则。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接