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?
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 }
Use Maybe
, which accurately models the response expecting either 0 results, 1 result or an exception.
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)