39

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.

Zain
  • 37,492
  • 7
  • 60
  • 84
Gaurav Vashisth
  • 7,547
  • 8
  • 35
  • 56

9 Answers9

66

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
Tom Insam
  • 701
  • 4
  • 7
  • I am getting: Each bind variable in the query must have a matching method parameter. Cannot find method parameters for :arg1, :arg0 – Mladen Rakonjac Jul 13 '17 at 15:53
  • 1
    Note that as of April 2019 having done an update to android studio on an old project, updated room to v1.1.1 i found that using arg0 was actually the problem, and i had to edit my DOA files to replace arg0 to match the function parameter name. i.e. arg0 became countryId. – Emile Apr 03 '19 at 14:46
13

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.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Clocker
  • 1,316
  • 2
  • 19
  • 29
8

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.

Prilaga
  • 818
  • 10
  • 18
6

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.

Zain
  • 37,492
  • 7
  • 60
  • 84
1

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

Anton Kazakov
  • 2,740
  • 3
  • 23
  • 34
1

None of the previous solutions worked for me. I had the @Dao files and the @Database file in different modules.

I had to put all the files (related to Room) in the same module for the error to disappear.

benjiii
  • 413
  • 3
  • 9
  • This was the only working solution when I trying to export the DB schema as described here: https://stackoverflow.com/a/48674264/2664521 on this android developer training app: https://github.com/google-developer-training/android-basics-kotlin-bus-schedule-app – CyclingSir Jun 29 '22 at 17:27
0

Seems fixed in kotlin-gradle-plugin:1.1.3

Alexander Perfilyev
  • 6,739
  • 2
  • 17
  • 30
0

As Anton Kazakov said this bug is fixed in kotlin plugin 1.1.3-eap-85

but since it is not public yet you need to download it from their privet repository, not jcenter

so you need to add this line in your build.gradle

 maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }

example

buildscript {
    ext {
        kotlin_version = '1.1.3-eap-85'
    }

    repositories {
        google()
        jcenter()
        maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha7'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
    }
}
humazed
  • 74,687
  • 32
  • 99
  • 138
0

This issues has been fixed int room 1.1.0-alpha3.

More information about this issues is here :

https://issuetracker.google.com/issues/68118746