简体   繁体   中英

How to build RoomDB in Kotlin with @Embedded table which contains some entity tables and the same @Embedded table, which contains entity too?

error: The class must be either @Entity or @DatabaseView. public final class StructuralObjectItemDB { ^

I have the following structure of data (from Json): 在此处输入图像描述

I want to get the database with tables: BuildingItemEntityDB, StructuralObjectItemEntityDB, AddressOjectItemEntityDB and IconItemEntityDB. In order to write method getItems() for "Building Items" (which includes AddressItemEntityDB and List of StructuralObjectItemDB) I've made BuildingItemDB with @Embedded annotation and two @Relations. Also I've made class StructuralObjectItemDB (which includes IconItemEntityDB) in order to write method getItems() for "StructuralObject Items". The problem is that RoomDB can't let me store StructuralObjectItemDB in BuildingItemDB as this is not @Entity or @DatabaseView, but I need it. What can I do in this situation?

BuildingItemDB.kt

package com.example.data.roomDB.entities.buildingItem

import androidx.room.Embedded
import androidx.room.Relation
import com.example.data.roomDB.entities.buildingItem.adressItem.AddressItemEntityDB
import com.example.data.roomDB.entities.buildingItem.structuralObjectItem.StructuralObjectItemDB

data class BuildingItemDB (

    @Embedded
    val buildingItemEntityDB: BuildingItemEntityDB,

    @Relation(
        parentColumn = "id",
        entityColumn = "buildingItemId"
    )
    val structuralObjectEntities: List<StructuralObjectItemDB>,

    @Relation(
        parentColumn = "id",
        entityColumn = "buildingItemId"
    )
    val address: AddressItemEntityDB,

    )

BuildingItemEntity.kt

package com.example.data.roomDB.entities.buildingItem

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "buildings")
data class BuildingItemEntityDB(

    @PrimaryKey
    val id: String,

    @ColumnInfo(name = "inventoryUsrreNumber")
    val inventoryUsrreNumber: String?,

    @ColumnInfo(name = "name")
    val name: String?,

    @ColumnInfo(name = "isModern")
    val isModern: Boolean?,

    @ColumnInfo(name = "type")
    val type: String?,

    @ColumnInfo(name = "markerPath")
    val markerPath: String?

)

BuildingItemDAO.kt

package com.example.data.roomDB.entities.buildingItem

import androidx.room.*
import com.example.data.roomDB.entities.buildingItem.adressItem.AddressItemDAO
import com.example.data.roomDB.entities.buildingItem.adressItem.AddressItemEntityDB
import com.example.data.roomDB.entities.buildingItem.structuralObjectItem.StructuralObjectItemDAO
import kotlinx.coroutines.flow.Flow

@Dao
interface BuildingItemDAO : StructuralObjectItemDAO, AddressItemDAO {

    // This operations are needed for entities. We'll use it in more difficult queries
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertBuildingItemEntityDB(buildingItemEntityDB: BuildingItemEntityDB): Long
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAddressItemEntityDB(address: AddressItemEntityDB?): Long
    @Update
    fun updateBuildingItemEntityDB(buildingItemEntityDB: BuildingItemEntityDB)
    @Update
    fun updateAddressItemEntityDB(address: AddressItemEntityDB?)
    @Delete
    fun deleteBuildingItemEntityDB(buildingItemEntityDB: BuildingItemEntityDB)
    @Delete
    fun deleteAddressItemEntityDB(address: AddressItemEntityDB?)

    @Transaction
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertOneBuildingItem(item: BuildingItemDB): Long {
        val resultValue = insertBuildingItemEntityDB(item.buildingItemEntityDB)
        insertStructuralObjectItemsList(item.structuralObjectEntities)
        insertAddressItemEntityDB(item.address)
        return resultValue
    }

    @Transaction
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertBuildingItemsList(items: List<BuildingItemDB>) {
        for (bi: BuildingItemDB in items) {
            insertOneBuildingItem(bi)
        }
    }

    @Transaction
    @Update
    suspend fun updateOneBuildingItem(item: BuildingItemDB) {
        updateBuildingItemEntityDB(item.buildingItemEntityDB)
        updateAllStructuralObjectItems(item.structuralObjectEntities)
        updateAddressItemEntityDB(item.address)
    }

    @Transaction
    @Update
    suspend fun updateAllBuildingItems(items: List<BuildingItemDB>) {
        for (bi: BuildingItemDB in items) {
            updateOneBuildingItem(bi)
        }
    }

    @Transaction
    @Delete
    suspend fun deleteOneBuildingItem(item: BuildingItemDB, deleteChildLocations: Boolean) {
        if (deleteChildLocations) {
            deleteAllStructuralObjectItems(item.structuralObjectEntities, deleteChildLocations)
            deleteAddressItemEntityDB(item.address)
        }
        deleteBuildingItemEntityDB(item.buildingItemEntityDB)
    }

    @Transaction
    @Delete
    suspend fun deleteAllBuildingItems(items: List<BuildingItemDB>, deleteChildLocations: Boolean) {
        for (bi: BuildingItemDB in items) {
            deleteOneBuildingItem(bi, deleteChildLocations)
        }
    }

    @Transaction
    @Query("SELECT * FROM buildings ORDER BY id")
    fun getAllBuildingItems(): Flow<List<BuildingItemDB>>

    @Transaction
    @Query("SELECT * FROM buildings WHERE id = :neededId")
    fun getBuildingItemById(neededId: String): Flow<BuildingItemDB>

}

StructuralObjectItemDB.kt

package com.example.data.roomDB.entities.buildingItem.structuralObjectItem

import androidx.room.*
import com.example.data.roomDB.entities.buildingItem.structuralObjectItem.iconItem.IconItemEntityDB

data class StructuralObjectItemDB(

    @Embedded
    val structuralItemsEntityDB: StructuralObjectItemEntityDB,

    @ColumnInfo(name = "buildingItemId")
    val buildingItemId: String?,

    @Relation(
        parentColumn = "id",
        entityColumn = "structuralObjectItemId"
    )
    val icon: IconItemEntityDB,

    )

StructuralObjectItemEntityDB.kt

package com.example.data.roomDB.entities.buildingItem.structuralObjectItem

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "structuralObjects")
data class StructuralObjectItemEntityDB(

    @PrimaryKey
    val id: String,

    @ColumnInfo(name = "subdivision")
    val subdivision: String?,

    @ColumnInfo(name = "description")
    val description: String?,

    @ColumnInfo(name = "website")
    val website: String?,

    @ColumnInfo(name = "buildingId")
    val buildingId: String?,

    @ColumnInfo(name = "category")
    val category: String?,

)

StructuralObjectItemDAO.kt

package com.example.data.roomDB.entities.buildingItem.structuralObjectItem

import androidx.room.*
import com.example.data.roomDB.entities.buildingItem.structuralObjectItem.iconItem.IconItemDAO
import com.example.data.roomDB.entities.buildingItem.structuralObjectItem.iconItem.IconItemEntityDB
import kotlinx.coroutines.flow.Flow

@Dao
interface StructuralObjectItemDAO : IconItemDAO {

    // This operations are needed for entities. We'll use it in more difficult queries
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertStructuralObjectItemEntityDB(structuralItemsEntityDB: StructuralObjectItemEntityDB): Long
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertIconItemEntityDB(icon: IconItemEntityDB?): Long
    @Update
    fun updateStructuralObjectItemEntityDB(structuralItemsEntityDB: StructuralObjectItemEntityDB)
    @Update
    fun updateIconItemEntityDB(icon: IconItemEntityDB?)
    @Delete
    fun deleteStructuralObjectItemEntityDB(structuralItemsEntityDB: StructuralObjectItemEntityDB)
    @Delete
    fun deleteIconItemEntityDB(icon: IconItemEntityDB?)

    @Transaction
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertOneStructuralObjectItem(item: StructuralObjectItemDB): Long {
        val resultValue = insertStructuralObjectItemEntityDB(item.structuralItemsEntityDB)
        insertIconItemEntityDB(item.icon)
        return resultValue
    }

    @Transaction
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertStructuralObjectItemsList(items: List<StructuralObjectItemDB>) {
        for (soi: StructuralObjectItemDB in items) {
            insertOneStructuralObjectItem(soi)
        }
    }

    @Transaction
    @Update
    suspend fun updateOneStructuralObjectItem(item: StructuralObjectItemDB) {
        updateStructuralObjectItemEntityDB(item.structuralItemsEntityDB)
        updateIconItemEntityDB(item.icon)
    }

    @Transaction
    @Update
    suspend fun updateAllStructuralObjectItems(items: List<StructuralObjectItemDB>) {
        for (soi: StructuralObjectItemDB in items) {
            updateOneStructuralObjectItem(soi)
        }
    }

    @Transaction
    @Delete
    suspend fun deleteOneStructuralObjectItem(item: StructuralObjectItemDB, deleteChildLocations: Boolean) {
        if (deleteChildLocations) {
            deleteIconItemEntityDB(item.icon)
        }
        deleteStructuralObjectItemEntityDB(item.structuralItemsEntityDB)
    }

    @Transaction
    @Delete
    suspend fun deleteAllStructuralObjectItems(items: List<StructuralObjectItemDB>, deleteChildLocations: Boolean) {
        for (soi: StructuralObjectItemDB in items) {
            deleteOneStructuralObjectItem(soi, deleteChildLocations)
        }
    }

    @Transaction
    @Query("SELECT * FROM structuralObjects ORDER BY id")
    fun getAllStructuralObjectItems(): Flow<List<StructuralObjectItemDB>>

    @Transaction
    @Query("SELECT * FROM structuralObjects WHERE id = :neededId")
    fun getStructuralObjectItemById(neededId: String): Flow<StructuralObjectItemDB>

}

AddressItemEntity.kt

package com.example.data.roomDB.entities.buildingItem.adressItem

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "addresses")
data class AddressItemEntityDB(

    @PrimaryKey
    val id: String,

    @ColumnInfo(name = "buildingItemId")
    val buildingItemId: String?,

    @ColumnInfo(name = "description")
    val description: String?,

    @ColumnInfo(name = "latitude")
    val latitude: String?,

    @ColumnInfo(name = "longitude")
    val longitude: String?

)

AddressItemDAO.kt

package com.example.data.roomDB.entities.buildingItem.adressItem

import androidx.room.*
import kotlinx.coroutines.flow.Flow

@Dao
interface AddressItemDAO {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertOneAddressItem(item: AddressItemEntityDB)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAddressItemsList(items: List<AddressItemEntityDB>)

    @Update
    suspend fun updateOneAddressItem(item: AddressItemEntityDB)

    @Update
    suspend fun updateAllAddressItems(items: List<AddressItemEntityDB>)

    @Delete
    suspend fun deleteOneAddressItem(item: AddressItemEntityDB)

    @Delete
    suspend fun deleteAllAddressItems(items: List<AddressItemEntityDB>)

    @Query("SELECT * FROM addresses ORDER BY id")
    fun getAllAddressItems(): Flow<List<AddressItemEntityDB>>

    @Query("SELECT * FROM addresses WHERE id = :neededId")
    fun getAddressItemById(neededId: String): Flow<AddressItemEntityDB>

}

IconItemEntityDB.kt

package com.example.data.roomDB.entities.buildingItem.structuralObjectItem.iconItem

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "icons")
data class IconItemEntityDB(

    @PrimaryKey
    val id: String,

    @ColumnInfo(name = "structuralObjectItemId")
    val structuralObjectItemId: String?,

    @ColumnInfo(name = "subdivision")
    val subdivision: String?,

    @ColumnInfo(name = "logoPath")
    val logoPath: String?

)

IconItemDAO.kt

package com.example.data.roomDB.entities.buildingItem.structuralObjectItem.iconItem

import androidx.room.*
import kotlinx.coroutines.flow.Flow

@Dao
interface IconItemDAO {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertOneIconItem(item: IconItemEntityDB)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertIconItemsList(items: List<IconItemEntityDB>)

    @Update
    suspend fun updateOneIconItem(item: IconItemEntityDB)

    @Update
    suspend fun updateAllIconItems(items: List<IconItemEntityDB>)

    @Delete
    suspend fun deleteOneIconItem(item: IconItemEntityDB)

    @Delete
    suspend fun deleteAllIconItems(items: List<IconItemEntityDB>)

    @Query("SELECT * FROM icons ORDER BY id")
    fun getAllIconItems(): Flow<List<IconItemEntityDB>>

    @Query("SELECT * FROM icons WHERE id = :neededId")
    fun getIconItemById(neededId: String): Flow<IconItemEntityDB>

}

I've solved my problem. The decision I did is to divide StructuralObjectItemDB into two entities (StructruralObjectItemEntityDB and IconItemEntityDB) and try to get them separately... So, we can work ONLY with Entities OR we can try @DatabaseView, but you need to write INNER JOIN query for it... Here is BuildingItemDB.kt now:

package com.example.data.roomDB.entities.buildingItem

import androidx.room.Embedded import androidx.room.Relation import com.example.data.roomDB.entities.buildingItem.adressItem.AddressItemEntityDB import com.example.data.roomDB.entities.buildingItem.structuralObjectItem.StructuralObjectItemEntityDB import com.example.data.roomDB.entities.buildingItem.structuralObjectItem.iconItem.IconItemEntityDB

data class BuildingItemDB (

// This class is needed for getItems() method in BuildingItemDAO
// This is a combination of:
// 1) AddressItemEntity table
// 2) StructuralObjectItemEntity table
// 3) IconItemEntityDB
// This class can only be used in SELECT queries, not in INSERT, UPDATE, DELETE

@Embedded
val buildingItemEntityDB: BuildingItemEntityDB,

@Relation(
    parentColumn = "id",
    entityColumn = "buildingItemId"
)
val structuralObjectEntities: List<StructuralObjectItemEntityDB>,

@Relation(
    parentColumn = "id",
    entityColumn = "buildingItemId"
)
val iconEntities: List<IconItemEntityDB>,

@Relation(
    parentColumn = "id",
    entityColumn = "buildingItemId"
)
val address: AddressItemEntityDB

)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM