J'utilise la bibliothèque de persistance Android Room avec kotlin.
Le Dao ressemble à ceci
@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
}
Cela me semble bien mais je reçois cette erreur
Error: Each bind variable in the query must have a matching method parameter. Cannot find method parameters for :countryId.
Je peux voir que le paramètre est nommé countryId
, alors quel peut être le problème?
FYI: Voici le code de génération dans 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();
}
}
Dans cette méthode, je vois que arg0 n'est utilisé nulle part dans la méthode.
EDIT: Cela semble être corrigé dans les nouveaux plugins. Plusieurs des réponses ici sont correctes, mais je ne peux pas accepter chaque réponse, désolé.
Kotlin ne conserve pas correctement les noms des arguments - c'est https://youtrack.jetbrains.com/issue/KT-17959
Vous pouvez contourner ce problème en utilisant :arg0
, :arg1
, etc. comme noms de paramètre dans vos instructions @Query:
@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
Avec kotlin v.1.2.10 et supérieur dans le projet pour moi, cela ne fonctionne que de la manière suivante:
@Query("select * from user where pk = :userId")
fun findUserById(userId: Long): DBUser
les noms ": userId " dans la requête et " userId " dans la méthode doivent être identiques.
Cette erreur se produit si vous n'avez pas défini apply plugin: 'kotlin-kapt'
dans votre build.gradle file. Si vous activez le plugin kapt, le compilateur fera correspondre le paramètre de liaison avec les arguments de la méthode comme prévu.
Ce problème peut maintenant être résolu avec 1.1.3-eap-85 et kotlin-kapt. Tweet officiel
Comme Anton Kazakov a dit que ce bug était corrigé dans le plugin kotlin 1.1.3-eap-85
mais comme il n'est pas encore public, vous devez le télécharger depuis leur dépôt privet, pas jcenter
vous devez donc ajouter cette ligne dans votre build.gradle
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
exemple
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' }
}
}
Ce problème a été corrigé dans la salle 1.1.0-alpha3.
Plus d'informations sur ces problèmes sont ici:
Semble corrigé dans kotlin-gradle-plugin: 1.1.3