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.
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
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.
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.
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.
This issue now can be fixed using 1.1.3-eap-85 and kotlin-kapt. Official tweet
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With