Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
737 views
in Technique[技术] by (71.8m points)

dao - Optional query parameters for Android Room

I have the following DAO with a query:

@Dao
public interface BaseballCardDao {
    @Query(
        "SELECT * FROM baseball_cards " +
        "WHERE brand LIKE :brand " +
        "  AND year = :year " +
        "  AND number LIKE :number " +
        "  AND player_name LIKE :playerName " +
        "  AND team LIKE :team"
    )
    LiveData<List<BaseballCard>> getBaseballCards(
        String brand, int year, String number, String playerName, String team
    );
}

The String parameters are "optional" in the sense that I can pass "%%" to match all rows due to the LIKE operator. But I cannot do this with year since it is an int. One solution is to add two different @Query methods, one with the int year parameter and the other without. Is there a more elegant way to create an optional parameter with Room's @Query?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is a late answer but as I have faced it recently, I wanted to share my simple (but silly!) trick for those who are looking for it.

As @CommonsWare has said, we can add an OR statement that checks for null to it and then simply make our optional parameters nullable and pass null for them. For example, your query would look like:

@Dao
public interface BaseballCardDao {
    @Query(
        "SELECT * FROM baseball_cards " +
        "WHERE (:brand IS NULL OR brand LIKE :brand)" +
        "  AND (:year IS NULL OR year = :year)" +
        "  AND (:number IS NULL OR number LIKE :number)" +
        "  AND (:playerName IS NULL OR player_name LIKE :playerName)" +
        "  AND (:team IS NULL OR team LIKE :team)"
    )
    LiveData<List<BaseballCard>> getBaseballCards(
        @Nullable String brand, @Nullable Integer year, @Nullable String number, @Nullable String playerName, @Nullable String team
    );
}

Or more declarative using kotlin and optional parameters:

@Query(
    """SELECT * FROM baseball_cards 
        WHERE (:brand IS NULL OR brand LIKE :brand) 
        AND (:year IS NULL OR year = :year) 
        AND (:number IS NULL OR number LIKE :number) 
        AND (:playerName IS NULL OR player_name LIKE :playerName)
        AND (:team IS NULL OR team LIKE :team)"""
)
fun getBaseballCards(
    brand: String? = null,
    year: Int? = null,
    number: String? = null,
    playerName: String? = null,
    team: String? = null
): LiveData<List<BaseballCard>>

Edit: Please consider that this solution is useful for non-nullable fields. If the field is nullable and you want to look for the records which don't have a value for the field, this is not the correct way of querying and you may consider dynamic query creation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...