title: How to build RoomDB in Kotlin with @Embedded table which contains some entity tables and the same @Embedded table, which contains entity too?
body: <p><strong>error: The class must be either @Entity or @DatabaseView.
  public final class StructuralObjectItemDB {
  ^</strong></p>
  <p>I have the following structure of data (from Json):
  <a href="https://i.stack.imgur.com/p4OSA.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/p4OSA.jpg" alt="enter image description here" /></a></p>
  <p>I want to get the database with tables: BuildingItemEntityDB, StructuralObjectItemEntityDB, AddressOjectItemEntityDB and IconItemEntityDB.
  In order to write method getItems() for &quot;Building Items&quot; (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 &quot;StructuralObject Items&quot;.
  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?</p>
  <p>BuildingItemDB.kt</p>
  <pre><code>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 = &quot;id&quot;,
          entityColumn = &quot;buildingItemId&quot;
      )
      val structuralObjectEntities: List&lt;StructuralObjectItemDB&gt;,
  
      @Relation(
          parentColumn = &quot;id&quot;,
          entityColumn = &quot;buildingItemId&quot;
      )
      val address: AddressItemEntityDB,
  
      )
  </code></pre>
  <p>BuildingItemEntity.kt</p>
  <pre><code>package com.example.data.roomDB.entities.buildingItem
  
  import androidx.room.ColumnInfo
  import androidx.room.Entity
  import androidx.room.PrimaryKey
  
  @Entity(tableName = &quot;buildings&quot;)
  data class BuildingItemEntityDB(
  
      @PrimaryKey
      val id: String,
  
      @ColumnInfo(name = &quot;inventoryUsrreNumber&quot;)
      val inventoryUsrreNumber: String?,
  
      @ColumnInfo(name = &quot;name&quot;)
      val name: String?,
  
      @ColumnInfo(name = &quot;isModern&quot;)
      val isModern: Boolean?,
  
      @ColumnInfo(name = &quot;type&quot;)
      val type: String?,
  
      @ColumnInfo(name = &quot;markerPath&quot;)
      val markerPath: String?
  
  )
  </code></pre>
  <p>BuildingItemDAO.kt</p>
  <pre><code>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&lt;BuildingItemDB&gt;) {
          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&lt;BuildingItemDB&gt;) {
          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&lt;BuildingItemDB&gt;, deleteChildLocations: Boolean) {
          for (bi: BuildingItemDB in items) {
              deleteOneBuildingItem(bi, deleteChildLocations)
          }
      }
  
      @Transaction
      @Query(&quot;SELECT * FROM buildings ORDER BY id&quot;)
      fun getAllBuildingItems(): Flow&lt;List&lt;BuildingItemDB&gt;&gt;
  
      @Transaction
      @Query(&quot;SELECT * FROM buildings WHERE id = :neededId&quot;)
      fun getBuildingItemById(neededId: String): Flow&lt;BuildingItemDB&gt;
  
  }
  </code></pre>
  <p>StructuralObjectItemDB.kt</p>
  <pre><code>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 = &quot;buildingItemId&quot;)
      val buildingItemId: String?,
  
      @Relation(
          parentColumn = &quot;id&quot;,
          entityColumn = &quot;structuralObjectItemId&quot;
      )
      val icon: IconItemEntityDB,
  
      )
  </code></pre>
  <p>StructuralObjectItemEntityDB.kt</p>
  <pre><code>package com.example.data.roomDB.entities.buildingItem.structuralObjectItem
  
  import androidx.room.ColumnInfo
  import androidx.room.Entity
  import androidx.room.PrimaryKey
  
  @Entity(tableName = &quot;structuralObjects&quot;)
  data class StructuralObjectItemEntityDB(
  
      @PrimaryKey
      val id: String,
  
      @ColumnInfo(name = &quot;subdivision&quot;)
      val subdivision: String?,
  
      @ColumnInfo(name = &quot;description&quot;)
      val description: String?,
  
      @ColumnInfo(name = &quot;website&quot;)
      val website: String?,
  
      @ColumnInfo(name = &quot;buildingId&quot;)
      val buildingId: String?,
  
      @ColumnInfo(name = &quot;category&quot;)
      val category: String?,
  
  )
  </code></pre>
  <p>StructuralObjectItemDAO.kt</p>
  <pre><code>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&lt;StructuralObjectItemDB&gt;) {
          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&lt;StructuralObjectItemDB&gt;) {
          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&lt;StructuralObjectItemDB&gt;, deleteChildLocations: Boolean) {
          for (soi: StructuralObjectItemDB in items) {
              deleteOneStructuralObjectItem(soi, deleteChildLocations)
          }
      }
  
      @Transaction
      @Query(&quot;SELECT * FROM structuralObjects ORDER BY id&quot;)
      fun getAllStructuralObjectItems(): Flow&lt;List&lt;StructuralObjectItemDB&gt;&gt;
  
      @Transaction
      @Query(&quot;SELECT * FROM structuralObjects WHERE id = :neededId&quot;)
      fun getStructuralObjectItemById(neededId: String): Flow&lt;StructuralObjectItemDB&gt;
  
  }
  </code></pre>
  <p>AddressItemEntity.kt</p>
  <pre><code>package com.example.data.roomDB.entities.buildingItem.adressItem
  
  import androidx.room.ColumnInfo
  import androidx.room.Entity
  import androidx.room.PrimaryKey
  
  @Entity(tableName = &quot;addresses&quot;)
  data class AddressItemEntityDB(
  
      @PrimaryKey
      val id: String,
  
      @ColumnInfo(name = &quot;buildingItemId&quot;)
      val buildingItemId: String?,
  
      @ColumnInfo(name = &quot;description&quot;)
      val description: String?,
  
      @ColumnInfo(name = &quot;latitude&quot;)
      val latitude: String?,
  
      @ColumnInfo(name = &quot;longitude&quot;)
      val longitude: String?
  
  )
  </code></pre>
  <p>AddressItemDAO.kt</p>
  <pre><code>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&lt;AddressItemEntityDB&gt;)
  
      @Update
      suspend fun updateOneAddressItem(item: AddressItemEntityDB)
  
      @Update
      suspend fun updateAllAddressItems(items: List&lt;AddressItemEntityDB&gt;)
  
      @Delete
      suspend fun deleteOneAddressItem(item: AddressItemEntityDB)
  
      @Delete
      suspend fun deleteAllAddressItems(items: List&lt;AddressItemEntityDB&gt;)
  
      @Query(&quot;SELECT * FROM addresses ORDER BY id&quot;)
      fun getAllAddressItems(): Flow&lt;List&lt;AddressItemEntityDB&gt;&gt;
  
      @Query(&quot;SELECT * FROM addresses WHERE id = :neededId&quot;)
      fun getAddressItemById(neededId: String): Flow&lt;AddressItemEntityDB&gt;
  
  }
  </code></pre>
  <p>IconItemEntityDB.kt</p>
  <pre><code>package com.example.data.roomDB.entities.buildingItem.structuralObjectItem.iconItem
  
  import androidx.room.ColumnInfo
  import androidx.room.Entity
  import androidx.room.PrimaryKey
  
  @Entity(tableName = &quot;icons&quot;)
  data class IconItemEntityDB(
  
      @PrimaryKey
      val id: String,
  
      @ColumnInfo(name = &quot;structuralObjectItemId&quot;)
      val structuralObjectItemId: String?,
  
      @ColumnInfo(name = &quot;subdivision&quot;)
      val subdivision: String?,
  
      @ColumnInfo(name = &quot;logoPath&quot;)
      val logoPath: String?
  
  )
  </code></pre>
  <p>IconItemDAO.kt</p>
  <pre><code>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&lt;IconItemEntityDB&gt;)
  
      @Update
      suspend fun updateOneIconItem(item: IconItemEntityDB)
  
      @Update
      suspend fun updateAllIconItems(items: List&lt;IconItemEntityDB&gt;)
  
      @Delete
      suspend fun deleteOneIconItem(item: IconItemEntityDB)
  
      @Delete
      suspend fun deleteAllIconItems(items: List&lt;IconItemEntityDB&gt;)
  
      @Query(&quot;SELECT * FROM icons ORDER BY id&quot;)
      fun getAllIconItems(): Flow&lt;List&lt;IconItemEntityDB&gt;&gt;
  
      @Query(&quot;SELECT * FROM icons WHERE id = :neededId&quot;)
      fun getIconItemById(neededId: String): Flow&lt;IconItemEntityDB&gt;
  
  }
  </code></pre>