Room Database如何校验用户名和邮箱是否已存在于数据表中
报错原因
你当前的DAO方法readUserName()声明返回LiveData<List<Customer>>,但SQL仅查询了userName单列,Room无法将单列查询结果映射为包含所有字段的Customer实体,因此抛出字段缺失错误。
解决方案
步骤1:修改CustomerDao,新增存在性校验查询
不用查询全表的用户名/邮箱再做对比,直接带参数查询目标值是否存在,查询效率更高:
@Dao interface CustomerDao { @Insert(onConflict = OnConflictStrategy.IGNORE) fun addCustomers(customer: Customer) @Query("SELECT * FROM cx_table ORDER BY id ASC") fun readAllData(): LiveData<List<Customer>> // 新增:检查用户名是否存在,存在返回1,不存在返回0 @Query("SELECT COUNT(*) FROM cx_table WHERE userName = :userName LIMIT 1") suspend fun isUserNameExists(userName: String): Int // 新增:检查邮箱是否存在,存在返回1,不存在返回0 @Query("SELECT COUNT(*) FROM cx_table WHERE email = :email LIMIT 1") suspend fun isEmailExists(email: String): Int }
步骤2:修改CustomerRepository,封装校验逻辑
class CustomerRepository(private val customerDao: CustomerDao) { val readAllData: LiveData<List<Customer>> = customerDao.readAllData() suspend fun addCustomer(customer: Customer){ customerDao.addCustomers(customer) } // 新增:用户名校验,存在返回true,不存在返回false suspend fun isUserNameExists(userName: String): Boolean { return customerDao.isUserNameExists(userName) > 0 } // 新增:邮箱校验,存在返回true,不存在返回false suspend fun isEmailExists(email: String): Boolean { return customerDao.isEmailExists(email) > 0 } }
步骤3:修改CustomerViewModel,对外暴露校验方法
class CustomerViewModel(application: Application): AndroidViewModel(application) { val readAllData: LiveData<List<Customer>> private val repository: CustomerRepository init { val customerDao = CustomerDatabase.getDatabase(application).customerDao() repository = CustomerRepository(customerDao) readAllData = repository.readAllData } fun addCustomer(customer: Customer){ viewModelScope.launch(Dispatchers.IO){ repository.addCustomer(customer) } } // 新增:校验用户名唯一性 suspend fun checkUserNameUnique(userName: String): Boolean { return withContext(Dispatchers.IO) { repository.isUserNameExists(userName) } } // 新增:校验邮箱唯一性 suspend fun checkEmailUnique(email: String): Boolean { return withContext(Dispatchers.IO) { repository.isEmailExists(email) } } }
步骤4:注册页调用校验逻辑
用户点击注册按钮时,先获取输入的用户名、邮箱,依次调用校验方法:
- 如果
checkUserNameUnique(输入的用户名)返回true,提示「用户名已被注册」 - 如果
checkEmailUnique(输入的邮箱)返回true,提示「邮箱已被注册」 - 两个校验都通过后,再调用
addCustomer插入用户数据
可选优化:加数据库唯一约束
为了避免并发场景下校验和插入的时间差导致脏数据,可直接给userName和email字段加数据库级唯一约束,双重保障:
修改Customer实体的@Entity注解:
@Entity( tableName = "cx_table", // 给userName、email加唯一索引 indices = [ Index(value = ["userName"], unique = true), Index(value = ["email"], unique = true) ] ) data class Customer( @PrimaryKey(autoGenerate = true) val id: Int, val firstName: String, val lastName: String, val userName: String, val password: String, val address: String, val city: String, val postalcode: String, val email: String, val phone: String )
内容的提问来源于stack exchange,提问作者user17312483
相关产品推荐
相关产品推荐

