Android Room持久化库中如何实现LIKE查询的大小写敏感?
在Android Room中实现大小写敏感的LIKE查询
我明白你遇到的问题了——设置PRAGMA case_sensitive_like = on后没生效,这其实是因为Room对数据库连接的管理方式导致的,单独执行这个PRAGMA语句可能无法覆盖所有Room使用的连接。下面给你几个可行的解决方案:
方案一:通过RoomDatabase Callback全局设置大小写敏感
Room允许我们在数据库打开时执行自定义SQL,我们可以利用这个特性,在每一个数据库连接打开时自动设置case_sensitive_like。这样所有的LIKE查询都会默认大小写敏感。
代码示例:
@Database(entities = [Category::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun categoryDao(): CategoryDao companion object { fun getInstance(context: Context): AppDatabase { return Room.databaseBuilder(context, AppDatabase::class.java, "your_db_name") .addCallback(object : RoomDatabase.Callback() { override fun onOpen(db: SupportSQLiteDatabase) { super.onOpen(db) // 在数据库打开时执行PRAGMA设置 db.execSQL("PRAGMA case_sensitive_like = ON") } }) .build() } } }
这个方法的好处是一次设置全局生效,不需要修改每个查询语句。
方案二:使用GLOB替代LIKE(原生大小写敏感)
SQLite的GLOB操作符默认就是大小写敏感的,它的匹配规则和LIKE类似,只是用*代替%,?代替_。你可以直接修改查询语句:
@Query("SELECT * FROM category WHERE category_name GLOB '*' || :categoryName || '*'") List<Category> getAllCategory(@Nullable String categoryName);
这个方法适合只需要单个查询大小写敏感的场景,不需要全局修改。
方案三:在查询中使用COLLATE BINARY
你可以在LIKE查询后加上COLLATE BINARY,强制使用大小写敏感的排序规则,这样也能实现需求:
@Query("SELECT * FROM category WHERE category_name LIKE '%' || :categoryName || '%' COLLATE BINARY") List<Category> getAllCategory(@Nullable String categoryName);
这个方法同样是针对单个查询,语法和原来的LIKE更贴近,学习成本更低。
为什么原来的PRAGMA设置没生效?
Room会维护自己的数据库连接池,如果你只是在某个单独的连接中执行PRAGMA case_sensitive_like = on,其他连接并不会继承这个设置。而通过RoomDatabase Callback的onOpen方法,Room会在每一个新打开的连接上执行这个SQL,确保所有连接都生效。
内容的提问来源于stack exchange,提问作者Lokesh
相关产品推荐
相关产品推荐

