Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Room (SQLite) WHERE clause with null arguments doesn't work

I have entity class Person and I want to query persons from database by feature which may or may not be null. When I set feature to non-null the query works but when the feature is null the query returns empty list. What I am doing wrong?

TEST

Context context = InstrumentationRegistry.getContext();
AppDb db = Room.inMemoryDatabaseBuilder(context, AppDb.class).allowMainThreadQueries().build();
PersonDao dao = db.personDao();

dao.insert(new Person("El Risitas", "Funny"));
dao.insert(new Person("Elon Musk", "Alien"));
dao.insert(new Person("Donald Trump", null));

assertEquals(3, dao.getAll().size());

assertEquals("Funny", dao.getByFeature("Funny").get(0).getFeature());

// fails because dao.getByFeature(null) = EMPTY LIST
assertEquals(null, dao.getByFeature(null).get(0).getFeature());

Person.java

import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;

@Entity(tableName = "person")
public class Person {

    @ColumnInfo(name = "id") @PrimaryKey(autoGenerate = true) private int id;
    @ColumnInfo(name = "name") private String name;
    @ColumnInfo(name = "feature") private String feature;

    public Person(String name, String feature) {
        this.name = name;
        this.feature = feature;
    }
    public void setId(int id) { this.id = id; }
    public int getId() { return id; }
    public String getName() { return name; }
    public String getFeature() { return feature; }
}

PersonDao.java

import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;

@Dao
public interface PersonDao {

    @Insert
    void insert(Person person);

    @Query("SELECT * FROM person")
    List<Person> getAll();

    @Query("SELECT * FROM person WHERE feature = :feature")
    List<Person> getByFeature(String feature);

}

AppDb.java

import androidx.room.Database;
import androidx.room.RoomDatabase;

@Database(
        version = 1,
        exportSchema = false,
        entities = {Person.class}
)
public abstract class AppDb extends RoomDatabase {

    public abstract PersonDao personDao();
}
like image 462
Egis Avatar asked Jul 09 '19 15:07

Egis


People also ask

Is room better than SQLite?

Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite. Room is now considered as a better approach for data persistence than SQLiteDatabase.

What is Dao in room?

When you use the Room persistence library to store your app's data, you interact with the stored data by defining data access objects, or DAOs. Each DAO includes methods that offer abstract access to your app's database. At compile time, Room automatically generates implementations of the DAOs that you define.

Does room use SQLite?

Room is a persistent library that is part of the Android jetpack. It is built on top of SQLite.

How do you delete data from a room?

3.1 Add the Clear all data menu optionIn the Options menu, select Clear all data. All words should disappear. Restart the app. (Restart it from your device or the emulator; don't run it again from Android Studio) You should see the initial set of words.


2 Answers

In SQL, nothing is ever equal to null. (Nothing is ever not equal to null, either.) You have to use is null. So your query could be something like (untested)

SELECT * FROM person WHERE feature = :feature or (feature is null and :feature is null)
like image 110
StackOverthrow Avatar answered Oct 01 '22 08:10

StackOverthrow


You can also use IS operator instead of =.

SELECT * FROM person WHERE feature IS :feature

From SQLite documentation:

The IS and IS NOT operators work like = and != except when one or both of the operands are NULL. In this case, if both operands are NULL, then the IS operator evaluates to 1 (true) and the IS NOT operator evaluates to 0 (false). If one operand is NULL and the other is not, then the IS operator evaluates to 0 (false) and the IS NOT operator is 1 (true). It is not possible for an IS or IS NOT expression to evaluate to NULL.

like image 34
Remc4 Avatar answered Oct 01 '22 08:10

Remc4