Add room database.

This commit is contained in:
Thomas Andres Gomez 2021-05-11 12:06:13 +02:00
parent 2ad8d5953a
commit 6a0710572a
17 changed files with 362 additions and 4 deletions

View file

@ -1,6 +1,7 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'org.jetbrains.kotlin.android'
}
@ -102,6 +103,14 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.google.code.gson:gson:2.8.6'
// Room
implementation "androidx.room:room-runtime:2.3.0"
implementation "androidx.room:room-ktx:2.3.0"
kapt "androidx.room:room-compiler:2.3.0"
// Paging
implementation "androidx.paging:paging-runtime-ktx:3.0.0"
// Test
testImplementation 'junit:junit:4.13.2'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.0.0-beta06"

View file

@ -3,8 +3,10 @@ package com.pixelized.biblib
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import androidx.room.Room
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.pixelized.biblib.database.BibLibDatabase
import com.pixelized.biblib.network.client.BibLibClient
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.repository.apiCache.APICacheRepository
@ -21,18 +23,23 @@ class BibLibApplication : Application() {
override fun onCreate() {
super.onCreate()
// Android.
Bob[BibLibDatabase::class] =
Room.databaseBuilder(this, BibLibDatabase::class.java, BibLibDatabase.DATABASE_NAME)
.build()
Bob[SharedPreferences::class] = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE)
// Web service.
Bob[Gson::class] = GsonBuilder().create()
Bob[BitmapCache::class] = BitmapCache(this)
Bob[IBibLibClient::class] = BibLibClient()
// Bitmap cache.
Bob[BitmapCache::class] = BitmapCache(this)
// Repositories.
Bob[IGoogleSingInRepository::class] = GoogleSingInRepository(this)
Bob[ICredentialRepository::class] = CredentialRepository()
Bob[IAPICacheRepository::class] = APICacheRepository()
}
companion object {
const val SHARED_PREF = "BIB_LIB_SHARED_PREF"
private const val SHARED_PREF = "BIB_LIB_SHARED_PREF"
}
}

View file

@ -0,0 +1,37 @@
package com.pixelized.biblib.database
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.pixelized.biblib.database.converter.DateConverter
import com.pixelized.biblib.database.crossref.BookAuthorCrossRef
import com.pixelized.biblib.database.crossref.BookGenreCrossRef
import com.pixelized.biblib.database.dao.*
import com.pixelized.biblib.database.data.*
@Database(
entities = [
AuthorDbo::class,
BookDbo::class,
GenreDbo::class,
LanguageDbo::class,
SeriesDbo::class,
BookAuthorCrossRef::class,
BookGenreCrossRef::class,
],
version = BibLibDatabase.VERSION
)
@TypeConverters(DateConverter::class)
abstract class BibLibDatabase : RoomDatabase() {
abstract fun authorDao(): AuthorDao
abstract fun bookDao(): BookDao
abstract fun genreDao(): GenreDao
abstract fun languageDao(): LanguageDao
abstract fun seriesDao(): SeriesDao
companion object {
const val VERSION = 1
const val DATABASE_NAME = "BibLibDataBase"
}
}

View file

@ -0,0 +1,12 @@
package com.pixelized.biblib.database.converter
import androidx.room.TypeConverter
import java.util.*
class DateConverter {
@TypeConverter
fun fromTimestamp(value: Long?): Date? = value?.let { Date(it) }
@TypeConverter
fun dateToTimestamp(date: Date?): Long? = date?.time
}

View file

@ -0,0 +1,14 @@
package com.pixelized.biblib.database.crossref
import androidx.room.ColumnInfo
import androidx.room.Entity
import com.pixelized.biblib.database.data.AuthorDbo
import com.pixelized.biblib.database.data.BookDbo
@Entity(primaryKeys = [BookDbo.ID, AuthorDbo.ID])
data class BookAuthorCrossRef(
@ColumnInfo(name = BookDbo.ID)
val bookId: String,
@ColumnInfo(name = AuthorDbo.ID)
val authorId: String
)

View file

@ -0,0 +1,14 @@
package com.pixelized.biblib.database.crossref
import androidx.room.ColumnInfo
import androidx.room.Entity
import com.pixelized.biblib.database.data.BookDbo
import com.pixelized.biblib.database.data.GenreDbo
@Entity(primaryKeys = [BookDbo.ID, GenreDbo.ID])
data class BookGenreCrossRef(
@ColumnInfo(name = BookDbo.ID)
val bookId: String,
@ColumnInfo(name = GenreDbo.ID)
val genreId: String
)

View file

@ -0,0 +1,16 @@
package com.pixelized.biblib.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.pixelized.biblib.database.data.AuthorDbo
@Dao
interface AuthorDao {
@Query("SELECT * FROM ${AuthorDbo.TABLE} WHERE ${AuthorDbo.ID} LIKE :id")
fun get(id: String?): AuthorDbo?
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg authors: AuthorDbo)
}

View file

@ -0,0 +1,18 @@
package com.pixelized.biblib.database.dao
import androidx.room.*
import com.pixelized.biblib.database.data.BookDbo
import com.pixelized.biblib.database.relation.BookRelation
@Dao
interface BookDao {
@Transaction
@Query("SELECT * FROM ${BookDbo.TABLE}")
fun getAll(): List<BookRelation>
@Insert
fun update(vararg books: BookDbo)
@Delete
fun delete(book: BookDbo)
}

View file

@ -0,0 +1,16 @@
package com.pixelized.biblib.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.pixelized.biblib.database.data.GenreDbo
@Dao
interface GenreDao {
@Query("SELECT * FROM ${GenreDbo.TABLE} WHERE ${GenreDbo.ID} LIKE :id")
fun get(id: String?): GenreDbo?
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg genres: GenreDbo)
}

View file

@ -0,0 +1,16 @@
package com.pixelized.biblib.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.pixelized.biblib.database.data.LanguageDbo
@Dao
interface LanguageDao {
@Query("SELECT * FROM ${LanguageDbo.TABLE} WHERE ${LanguageDbo.ID} LIKE :id")
fun get(id: String?): LanguageDbo?
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg languages: LanguageDbo)
}

View file

@ -0,0 +1,16 @@
package com.pixelized.biblib.database.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.pixelized.biblib.database.data.SeriesDbo
@Dao
interface SeriesDao {
@Query("SELECT * FROM ${SeriesDbo.TABLE} WHERE ${SeriesDbo.ID} LIKE :id")
fun get(id: String?): SeriesDbo?
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg series: SeriesDbo)
}

View file

@ -0,0 +1,23 @@
package com.pixelized.biblib.database.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = AuthorDbo.TABLE)
data class AuthorDbo(
@PrimaryKey
@ColumnInfo(name = ID)
val id: String,
@ColumnInfo(name = NAME)
val name: String,
@ColumnInfo(name = SORT)
val sort: String,
) {
companion object {
const val TABLE = "AUTHOR"
const val ID = "${TABLE}_ID"
const val NAME = "${TABLE}_NAME"
const val SORT = "${TABLE}_SORT"
}
}

View file

@ -0,0 +1,58 @@
package com.pixelized.biblib.database.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.*
@Entity(tableName = BookDbo.TABLE)
data class BookDbo(
@PrimaryKey
@ColumnInfo(name = ID)
val id: Int,
@ColumnInfo(name = TITLE)
val title: String,
@ColumnInfo(name = SORT)
val sort: String,
@ColumnInfo(name = HAVE_COVER)
val haveCover: Boolean,
@ColumnInfo(name = RELEASE_DATE)
val releaseDate: Date,
@ColumnInfo(name = LANGUAGE_ID)
val language: String? = null, // one-to-many
@ColumnInfo(name = RATING)
val rating: Int? = null,
// details
@ColumnInfo(name = SERIES_ID)
val series: String? = null, // one-to-many
@ColumnInfo(name = SYNOPSIS)
val synopsis: String? = null,
// source
@ColumnInfo(name = IS_NEW)
val isNew: Boolean = false,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is BookDbo) return false
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id
}
companion object {
const val TABLE = "BOOK"
const val ID = "${TABLE}_ID"
const val TITLE = "${TABLE}_TITLE"
const val SORT = "${TABLE}_SORT"
const val HAVE_COVER = "${TABLE}_HAVE_COVER"
const val RELEASE_DATE = "${TABLE}_RELEASE_DATE"
const val LANGUAGE_ID = "${TABLE}_LANGUAGE_ID"
const val RATING = "${TABLE}_RATING"
const val SERIES_ID = "${TABLE}_SERIES_ID"
const val SYNOPSIS = "${TABLE}_SYNOPSIS"
const val IS_NEW = "${TABLE}_ISNEW"
}
}

View file

@ -0,0 +1,20 @@
package com.pixelized.biblib.database.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = GenreDbo.TABLE)
data class GenreDbo(
@PrimaryKey
@ColumnInfo(name = ID)
val id: String,
@ColumnInfo(name = NAME)
val name: String,
) {
companion object {
const val TABLE = "GENRE"
const val ID = "${TABLE}_ID"
const val NAME = "${TABLE}_NAME"
}
}

View file

@ -0,0 +1,21 @@
package com.pixelized.biblib.database.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = LanguageDbo.TABLE)
data class LanguageDbo(
@PrimaryKey
@ColumnInfo(name = ID)
val id: String,
@ColumnInfo(name = NAME)
val code: String,
) {
companion object {
const val TABLE = "LANGUAGE"
const val ID = "${TABLE}_ID"
const val NAME = "${TABLE}_NAME"
}
}

View file

@ -0,0 +1,26 @@
package com.pixelized.biblib.database.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = SeriesDbo.TABLE)
data class SeriesDbo(
@PrimaryKey
@ColumnInfo(name = ID)
val id: String,
@ColumnInfo(name = NAME)
val name: String,
@ColumnInfo(name = SORT)
val sort: String,
@ColumnInfo(name = INDEX)
val index: Int?,
) {
companion object {
const val TABLE = "SERIES"
const val ID = "${TABLE}_ID"
const val NAME = "${TABLE}_NAME"
const val SORT = "${TABLE}_SORT"
const val INDEX = "${TABLE}_INDEX"
}
}

View file

@ -0,0 +1,35 @@
package com.pixelized.biblib.database.relation
import androidx.room.Embedded
import androidx.room.Junction
import androidx.room.Relation
import com.pixelized.biblib.database.crossref.BookAuthorCrossRef
import com.pixelized.biblib.database.crossref.BookGenreCrossRef
import com.pixelized.biblib.database.data.*
data class BookRelation(
@Embedded
val bookDbo: BookDbo,
@Relation(
parentColumn = BookDbo.ID,
entityColumn = AuthorDbo.ID,
associateBy = Junction(BookAuthorCrossRef::class)
)
val authors: List<AuthorDbo>,
@Relation(
parentColumn = BookDbo.ID,
entityColumn = GenreDbo.ID,
associateBy = Junction(BookGenreCrossRef::class)
)
val genres: List<GenreDbo>,
@Relation(
parentColumn = BookDbo.LANGUAGE_ID,
entityColumn = LanguageDbo.ID
)
val language: LanguageDbo,
@Relation(
parentColumn = BookDbo.SERIES_ID,
entityColumn = SeriesDbo.ID
)
val series: SeriesDbo,
)