Как сохранить список целых чисел в базе данных Room, чтобы его можно было легко запросить позже? - PullRequest
0 голосов
/ 04 мая 2020

Я храню данные подкаста в базе данных Room, где каждый подкаст имеет List<Int> с именем genreIds. Я хотел бы иметь возможность хранить это таким образом, чтобы я мог легко запросить его позже, выполнив что-то вроде SELECT * FROM podcasts WHERE genreIds CONTAINS :genre или любой другой команды.

Итак, каков наилучший способ хранения этот список Ints, чтобы его можно было легко запросить позже, и как мне это сделать с помощью Room? Я использовал TypeConverters раньше, но это преобразует его в строку, которую сложно запросить, поэтому я хотел бы иметь возможность связать ее с другой таблицей или чем-то, что может быть легко запрошено, я просто не конечно, как это сделать.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

Я нашел [эту статью на Среднем] [1], что я нашел очень полезным. Я пытаюсь установить связь «многие ко многим», которая в этом случае будет выглядеть примерно так:

Podcast class:
@Entity(tableName = "podcasts")
data class Podcast(
    @PrimaryKey
    @ColumnInfo(name = "podcast_id")
    val id: String,
    // other fields
}

Класс жанра:

@Entity(tableName = "genres")
data class Genre (
    @PrimaryKey
    @ColumnInfo(name = "genre_id")
    val id: Int,
    val name: String,
    val parent_id: Int
)

Класс PodcastDetails:

data class PodcastDetails (
    @Embedded
    val podcast: Podcast,
    @Relation(
        parentColumn = "podcast_id",
        entityColumn = "genre_id",
        associateBy = Junction(PodcastGenreCrossRef::class)
    )
    val genres: List<Genre>
)

PodcastGenreCrossRef:

@Entity(primaryKeys = ["podcast_id", "genre_id"])
data class PodcastGenreCrossRef (
    val podcast_id: Int,
    val genre_id: Int
)

И получить к нему доступ в DAO следующим образом:

@Transaction
@Query(SELECT * FROM podcasts)
fun getPodcastsWithGenre() : List<PodcastDetails>

  [1]: https://medium.com/androiddevelopers/database-relations-with-room-544ab95e4542
0 голосов
/ 04 мая 2020

Данные, хранящиеся в БД с комнатой, зависят от класса данных, который вы используете. Если вы укажете класс данных с Int членом, это будет Int в БД.

Пример:

data class TrackPlayedDB (
    @PrimaryKey(autoGenerate = true)
    val _id: Int = 0,
    val timesPlayed: Int,
    val artist: String,
    val trackTitle: String,
    val playDateTime: LocalDateTime
)

здесь timesPlayed будет Int на БД (как _id). Вы будете определять свои классы данных, как показано ниже, это создаст соответствующие таблицы.

@Database(entities = [TrackPlayedDB::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyRoomDatabase : BaseRoomDatabase() {

Редактировать: После комментария автора, я исправлен, я не правильно понял вопрос.

Автор фактически спрашивает, как сохранить List<Int> как поле в таблице. Для этого есть 2 решения: одно, как предлагает автор, заключается в том, чтобы сохранить список в виде строки и использовать ключевое слово Like для написания запросов со следующим предложением:

SELECT * FROM mytable
WHERE column1 LIKE '%word1%'
   OR column1 LIKE '%word2%'
   OR column1 LIKE '%word3%'

в качестве простого поиска. на SO показало бы: SQL Поле SELECT WHERE содержит слова

Автор говорит, что он использовал TypeConverters, поэтому я пропущу, как преобразовать List<Int> в строку

Другим решением этой проблемы является осознание того, что ничего не было понято в теории транзакционных баз данных. Фактически, когда у вас есть отношение многие ко многим, как в случае подкаста и жанра, теория диктует, что вы создаете таблицу, которая связывает идентификаторы подкастов и идентификаторы жанров, как это объясняется здесь: https://dzone.com/articles/how-to-handle-a-many-to-many-relationship-in-datab и другие бесчисленные книги, видео и блоги. Это дает преимущества БД с добавленной ясностью, производительностью и масштабируемостью. Итог, авторский дизайн БД неверен.

...