Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Room : Each bind variable in the query must have a matching method

I am using the android persistence library Room with Kotlin.

The Dao looks like this

@Dao
interface CountryDao {
    @Query("SELECT * FROM countries")
    fun loadAllCountried() : LiveData<List<CountryEntity>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAll(products: List<CountryEntity>)

    @Query("SELECT * FROM countries WHERE id = :countryId")
    fun loadCountry(countryId: Int): LiveData<CountryEntity>

    @Query("SELECT * FROM countries WHERE id = :countryId")
    fun loadCountrySync(countryId: Int): CountryEntity

}

It seems good to me but I am getting this error

Error: Each bind variable in the query must have a matching method parameter. Cannot find method parameters for :countryId.

I can see the parameter is named as countryId, so what may be the issue?

FYI: Here is the generated code in CountryDao_Impl.java

@Override
public CountryEntity loadCountrySync(int arg0) {
  final String _sql = "SELECT * FROM countries WHERE id = ?";
  final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
  int _argIndex = 1;
  final Cursor _cursor = __db.query(_statement);
  try {
    final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
    final int _cursorIndexOfPopulation = _cursor.getColumnIndexOrThrow("population");
    final CountryEntity _result;
   if(_cursor.moveToFirst()) {
     _result = new CountryEntity();
      final int _tmpId;
      _tmpId = _cursor.getInt(_cursorIndexOfId);
      _result.setId(_tmpId);
      final long _tmpPopulation;
      _tmpPopulation = _cursor.getLong(_cursorIndexOfPopulation);
      _result.setPopulation(_tmpPopulation);
    } else {
      _result = null;
    }
    return _result;
  } finally {
    _cursor.close();
    _statement.release();
  }
}

In this method I see arg0 is not being used anywhere in the method.

EDIT: This seems to be fixed in the new plugins. Several of the answers here are correct, but I can't accept every answer, Sorry.

like image 239
Gaurav Vashisth Avatar asked May 26 '17 17:05

Gaurav Vashisth


5 Answers

Kotlin isn't preserving the names of the arguments properly - this is https://youtrack.jetbrains.com/issue/KT-17959

You can work around this by using :arg0, :arg1, etc, as parameter names in your @Query statements:

@Query("SELECT * FROM countries WHERE id = :arg0")
fun loadCountry(countryId: Int): LiveData<CountryEntity>

@Query("SELECT * FROM countries WHERE id = :arg0")
fun loadCountrySync(countryId: Int): CountryEntity
like image 171
Tom Insam Avatar answered Nov 16 '22 04:11

Tom Insam


This error occurs if you do not have apply plugin: 'kotlin-kapt' defined in your build.gradle file. If you do enable the kapt plugin, the compiler will match the binding parameter with the method arguments as expected.

like image 37
Clocker Avatar answered Nov 16 '22 03:11

Clocker


With kotlin v.1.2.10 and higher in the project for me it works only by next way:

@Query("select * from user where pk = :userId")
fun findUserById(userId: Long): DBUser

names ":userId" in the query and "userId" in the method should be the same.

like image 8
Prilaga Avatar answered Nov 16 '22 03:11

Prilaga


For me, this issue appeared when I change/add methods in either the DAO interface or database Entity classes, and I solved it by just Build > Clean Project followed by Build > Make Project. then run it.

like image 5
Zain Avatar answered Nov 16 '22 03:11

Zain


This issue now can be fixed using 1.1.3-eap-85 and kotlin-kapt. Official tweet

like image 1
Anton Kazakov Avatar answered Nov 16 '22 03:11

Anton Kazakov