Kann eine Abfrage zur Laufzeit erstellt werden?
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
List<IPlaylist> searchPlaylists(String playlistTitle, int limit);
Der Teil limit
ist optional. Das heißt, es sollte in der Lage sein, dieselbe Abfrage mit oder ohne Begrenzung auszuführen.
Im vorherigen Fall ist es möglich, zwei statische Abfragen mit und ohne Limit-Teil durchzuführen, und es kann jeweils ein entsprechender verwendet werden. Manchmal müssen wir uns jedoch mit komplexeren Situationen befassen, wie dem Erstellen eines Filters.
In diesem Fall gibt es im Gegensatz zum vorherigen Beispiel mehrere optionale Teile. Für eine Tabelle mit Büchern müssen wir möglicherweise nach der Kategorie filtern, zu der das Buch gehört, dem Namen des Autors, der Preisspanne, dem Veröffentlichungsdatum usw. Es ist fast unmöglich, statische Abfragen mit allen Kombinationen dieser Teile zu erstellen.
Nach meiner Erfahrung (kurz) mit Room ist dies nicht möglich, und zwar nicht, weil es sich um eine Raumbegrenzung handelt, sondern, wie von @CommonsWare implizit kommentiert, eine Einschränkung für SQLite. Sie benötigen zwei Abfragen und daher zwei Methoden in Ihrem DAO.
Ich hätte so etwas wie:
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
List<IPlaylist> searchPlaylists(String playlistTitle, int limit);
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title ")
List<IPlaylist> searchPlaylists(String playlistTitle);
Dann machen Sie woanders den Bypass:
if (limit.isPresent()) {
return playlistDao.searchPlaylists(title, limit.get());
} else {
return playlistDao.searchPlaylists(title);
}
Das ist die beste Option, die ich im Moment denken kann.
Anstatt mehrere Abfragen zu schreiben, verweise ich auf negative Klausel. Wenn es eine Änderung in der Abfrage gibt, muss ich die Abfrage aktualisieren, die fehleranfälliger ist.
Offizielles doc -> Wenn der LIMIT-Ausdruck einen negativen Wert ergibt, dann gibt es keine Obergrenze für die Anzahl der zurückgegebenen Zeilen. finden Sie es hier https://sqlite.org/lang_select.html und lesen Sie den Abschnitt über die Limitklausel.
Also würde ich so etwas tun,
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
List<IPlaylist> searchPlaylists(String playlistTitle, int limit);
und negativ übergeben, wenn Sie keinen Filter anwenden möchten.
return playlistDao.searchPlaylists(title, limit.isPresent() ? limit.get() : -1)
Es funktioniert in meinem Fall.
Aktualisiert [21. Dezember 2018]
Wenn Sie Kotlin verwenden, verwenden Sie den Standardwert.
@JvmOverloads
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
fun searchPlaylists(playlistTitle: String, limit: Int = -1): List<IPlaylist>
@JvmOverloads
, um es mit Java kompatibel zu machen. Es werden zwei separate Methoden für Java generiert.
In Room gibt es keine optionalen Parameter, aber es gibt eine @RawQuery-Annotation, in der Sie die Abfrage als String übergeben können, um Ihre SQL-Abfrage in der Laufzeit zu erstellen. Ich denke, das wird für dich funktionieren.
Hier ist das Beispiel aus der offiziellen Dokumentation:
@Dao
interface RawDao {
@RawQuery
User getUser(String query);
}
Und so können Sie es verwenden:
User user = rawDao.getUser("SELECT * FROM User WHERE id = 3 LIMIT 1");
Wichtig: RawQuery-Methoden müssen einen nicht ungültigen Typ zurückgeben
Wichtig: Dies ist in Raum 1.1.0-alpha3 verfügbar
Raum unterstützt @RawQuery
annotation zum Erstellen von Abfragen zur Laufzeit.
Markieren Sie die DAO-Methode mit @RawQuery
-Anmerkung anstelle von normalem @RawQuery
.
@Dao
interface BooksDao{
@RawQuery
List<Book> getBooks(SupportSQLiteQuery query);
}
Room verwendet vorbereitete Anweisungen für die Überprüfung der Sicherheit und der Kompilierzeit. Daher müssen beim Erstellen von Abfragen Abfragezeichenfolge- und Bindungsparameter separat gespeichert werden.
In diesem Beispiel verwende ich die Variable queryString
für die Abfragezeichenfolge und args
für die Bindeparameter.
(Bitte beachten Sie, dass ich Texteditor zum Schreiben von Code verwendet habe. Daher kann es zu Tippfehlern oder einfachen Syntaxfehlern kommen. Wenn Sie etwas finden, lassen Sie es mich in den Kommentaren wissen oder bearbeiten Sie den Beitrag.)
// Query string
String queryString = new String();
// List of bind parameters
List<Object> args = new ArrayList();
boolean containsCondition = false;
// Beginning of query string
queryString += "SELECT * FROM BOOKS";
// Optional parts are added to query string and to args upon here
if(!authorName.isEmpty()){
queryString += " WHERE";
queryString += " author_name LIKE ?%";
args.add(authorName);
containsCondition = true;
}
if(fromDate!=null){
if (containsCondition) {
queryString += " AND";
} else {
queryString += " WHERE";
containsCondition = true;
}
queryString += " publication_date AFTER ?";
args.add(fromDate.getTime());
}
if(toDate!=null){
if (containsCondition) {
queryString += " AND";
} else {
queryString += " WHERE";
containsCondition = true;
}
queryString += " publication_date BEFORE ?";
args.add(toDate.getTime());
}
// End of query string
queryString += ";";
SimpleSQLiteQuery query = new SimpleSQLiteQuery(queryString, args.toArray());
List<Book> result = booksDao.getBooks(query);
Query
unterstützt RawQuery
die Rückgabe von rohen Cursors, Entitäten, POJOs und POJOs mit eingebetteten FeldernRawQuery
unterstützt BeziehungenVerwenden Sie SupportSQLiteQuery.
https://developer.Android.com/reference/Android/Arch/persistence/db/SupportSQLiteQuery
Die neueste Version 1.1.1 verwendet jetzt SupportSQLiteQuery.
Eine Abfrage mit typisierten Bindungen. Es ist besser, diese API anstelle von .__ zu verwenden. rawQuery (String, String []), da der sichere Bindungstyp zulässig ist Parameter.
@Dao
interface RawDao {
@RawQuery(observedEntities = User.class)
LiveData<List<User>> getUsers(SupportSQLiteQuery query);
}
Verwendungszweck:
LiveData<List<User>> liveUsers = rawDao.getUsers( new
SimpleSQLiteQuery("SELECT * FROM User ORDER BY name DESC"));
Aktualisieren Sie Ihren Gradle auf 1.1.1
implementation 'Android.Arch.persistence.room:runtime:1.1.1'
implementation 'Android.Arch.lifecycle:extensions:1.1.1'
annotationProcessor "Android.Arch.persistence.room:compiler:1.1.1"
Hinweis: Wenn Sie ein Upgrade auf 1.1.1 durchführen und String anstelle von SupportSQLiteQuery verwenden,
sie erhalten den Fehler:
RawQuery lässt keine Zeichenfolge mehr zu. Benutzen Sie bitte Android.Arch.persistence.db.SupportSQLiteQuery.
Wenn Sie SupportSQLiteQuery wie oben beschrieben verwenden, wird das Problem gelöst.
Hinweis: Stellen Sie sicher, dass Sie den Abfrageparameter "SupportSQLiteQuery" übergeben. Andernfalls wird folgender Fehler angezeigt:
RawQuery-Methoden sollten 1 und nur 1 Parameter vom Typ String .__ haben. oder SupportSQLiteQuery
make it more simple.i will show you example using where clause using two variable.Do
like this
@Query("SELECT * FROM Student WHERE stdName1= :myname AND stdId1=:myid")
List<Student> fetchAllData(String myname,int myid);
stdName1 und stdId1 sind Spaltennamen