Android: Check if object is present in database us

2019-06-06 00:30发布

问题:

I'm using Room as ORM and here is my Dao interface:

@Dao
interface UserDao {
    @Query(value = "SELECT * FROM User LIMIT 1")
    fun get(): Single<User?>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun add(profile: User)
}

In other hand I have a method in Repository which should check if the user is login or not, here is the implementation code:

override fun isUserLogin(): Single<Boolean> = userDao
            .get().async()
            .onErrorReturn { null }
            .map { it != null }

Room will throw the following exception if no row matches the query:

Query returned empty result set: SELECT * FROM User LIMIT 1

I want to return null in this case, but when I execute the code it throw an exception with the following messsage:

Value supplied was null

I can't use Optional because Dao is returning Single<User?> so onErrorReturn should return the same type.

How can I check if the user exists or not without changing Dao?

回答1:

I think the proper way to do this, besides Android and Room, is to use COUNT in your query.

@Query("SELECT COUNT(*) from User")
fun usersCount() : Single<Int>

It will return the number of rows in the table, if it's 0 you know there is no user in the db, so.

override fun isUserLogin(): Single<Int> = userDao
            .usersCount()
            .async()
            .map { it > 0 }

If you really want to do it the ugly way though:

@Query(value = "SELECT * FROM User LIMIT 1")
fun get(): Single<User>

Don't use a nullable type, it's pointless. Then map to Boolean and handle the exception:

override fun isUserLogin(): Single<Boolean> = userDao
        .get()
        .async()
        .map { true }
        .onErrorReturn { false }


回答2:

Use Maybe, which accurately models the response expecting either 0 results, 1 result or an exception.



回答3:

If you change your DAO to return a Flowable list of users you can then map this into a boolean value by checking the size of the list.

@Query(value = "SELECT * FROM User LIMIT 1")
fun get(): Flowable<List<User>> 

e.g.

fun isUserLogin(): Single<Boolean> = userDao
    .get()
    .flatMapSingle { Single.just(it.size == 1) }
    .onErrorReturn { false }
    .first(false)