ROOM数据库实体建模
ROOM database entity modeling
一定有更好的方法来做到这一点。我想创建一个包含我所有服装的数据库 table,并包含服装的子类别,如外衣、连衣裙、鞋子等。它们都将具有相同的属性(ID、名称、图像、关于、价格)。我不能创建一个 table 吗?我相信这是一个一对多的关系。
@Serializable
@Entity(tableName = CLOTHING_DATABASE_TABLE)
data class Clothing(
@PrimaryKey(autoGenerate = false)
val id: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = POPULAR_DATABASE_TABLE)
data class Popular(
@PrimaryKey(autoGenerate = false)
val popularId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = OUTERWEAR_DATABASE_TABLE)
data class Outerwear(
@PrimaryKey(autoGenerate = false)
val outerwearId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = TOPS_DATABASE_TABLE)
data class Tops(
@PrimaryKey(autoGenerate = false)
val topsId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = SWIMWEAR_DATABASE_TABLE)
data class Swimwear(
@PrimaryKey(autoGenerate = false)
val swimwearId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = SHOES_DATABASE_TABLE)
data class Shoes(
@PrimaryKey(autoGenerate = false)
val shoesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = BUNDLES_DATABASE_TABLE)
data class Bundles(
@PrimaryKey(autoGenerate = false)
val bundlesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = DRESSES_DATABASE_TABLE)
data class Dresses(
@PrimaryKey(autoGenerate = false)
val dressesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = PAJAMAS_DATABASE_TABLE)
data class Pajamas(
@PrimaryKey(autoGenerate = false)
val pajamasId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = ACCESSORIES_DATABASE_TABLE)
data class Accessories(
@PrimaryKey(autoGenerate = false)
val accessoriesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
您通常会有 2 或 3 个 table(3 个 many-many,即一件衣服可能有多个 sub-categories)。
对于 one-many 有一个 服装 table 其中有一列 sub-category 引用(相关)单个 sub-category 和一个 sub-category table 是根据唯一列(主键)引用的
对于many-many你有服装table(没有专栏参考单sub-category),sub-categorytable然后一个第三个 table 有两列,一列用于引用服装,另一列用于引用 sub-category,主键是两者的组合。
所以你可以:-
@Entity(tableName = CLOTHING_DATABASE_TABLE)
data class Clothing(
@PrimaryKey(autoGenerate = false)
val id: Long, /* should really be Long as */
val subCategoryReference: Long, /*<<<<< ADDED for the 1 subcategory */
val name: String,
val image: String,
val about: String,
val price: String
)
和:-
@Entity(tableName = SUBCATEGORY_DATABASE_TABLE)
data class SubCategory(
@PrimaryKey
val id: Long?,
val subCategoryName: String
)
- 要强制执行参照完整性,您可以将外键约束添加到服装的 subCategoryReference 列 table。
如果您想要一件 many-many,允许一件衣服有多个 sub-categories,那么您可以将第三个 table 作为 :-
@Entity(
tableName = CLOTHING_SUBCATEGORY_MAP_DATABASE_TABLE,
primaryKeys = ["clothingMap","subcategoryMap"],
)
data class ClothingSubCategoryMap(
val clothingMap: Long,
@ColumnInfo(index = true)
val subcategoryMap: Long
)
当然你可以有一件衣服 table 并且只有 sub-category 的一列。但是,这将被视为未规范化,因为您将在整个过程中复制 sub-category。
示例 1-many (即使用 2 tables 服装和子类别)
因为您很可能想要连同衣服一起检索 sub-category 那么您将拥有一个使用 @Embedded 和 @Relation 注释的 POJO,例如
data class ClothingWithSingleSubCategory (
@Embedded
val clothing: Clothing,
@Relation(
entity = SubCategory::class,
parentColumn = "subCategoryReference",
entityColumn = "id"
)
val subCategory: SubCategory
)
然后您可以将以下内容作为带注释的@Dao class :-
@Dao
interface AllDao {
@Insert(onConflict = IGNORE)
fun insert(clothing: Clothing): Long
@Insert(onConflict = IGNORE)
fun insert(subCategory: SubCategory): Long
@Transaction
@Query("SELECT * FROM clothing")
fun getAllClothingWithSubCategory(): List<ClothingWithSingleSubCategory>
}
使用 suitable @Database 注释 class 然后你可以在 activity:-
中有类似下面的内容
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val sc_popular = dao.insert(SubCategory(null,"Popular"))
val sc_outerwear = dao.insert(SubCategory(null,"OuterWear"))
val sc_tops = dao.insert(SubCategory(null,"Tops"))
val sc_swimwear = dao.insert(SubCategory(100,"Swimwear"))
val sc_shoes = dao.insert(SubCategory(null,"Shoes"))
val sc_dresses = dao.insert(SubCategory(null,"Dresses"))
val sc_pyjamas = dao.insert(SubCategory(null,"Pyjamas"))
dao.insert(Clothing(100200300400,sc_popular,"Jeans","jeans_image","blah","100.55"))
dao.insert(Clothing(100200300500,sc_outerwear,"Anorak","anorak_image","blah","214.55"))
for (cwsc: ClothingWithSingleSubCategory in dao.getAllClothingWithSubCategory()) {
Log.d("DBINFO","Name = ${cwsc.clothing.name} Price is ${cwsc.clothing.price} Sub-Category is ${cwsc.subCategory.subCategoryName}")
}
}
}
当 运行 日志将包括:-
D/DBINFO: Name = Jeans Price is 100.55 Sub-Category is Popular
D/DBINFO: Name = Anorak Price is 214.55 Sub-Category is OuterWear
示例many-many
与 1-many 一样,您需要一个 POJO,但它具有通过映射 table 获得的 sub-categories 列表。这使用 @Embeded 注释和 @Relation 注释,但扩展为包括 associateBy 以通知 Room 关于中间 table。所以你可以:-
data class ClothingWithListOfSubCategories(
@Embedded
val clothing: Clothing,
@Relation(
entity = SubCategory::class,
parentColumn = "id",
entityColumn = "id",
associateBy = Junction(
value = ClothingSubCategoryMap::class,
parentColumn = "clothingMap",
entityColumn = "subcategoryMap"
)
)
val subCategories: List<SubCategory>
)
您可以在带注释的@Dao 中包含以下内容 class:-
/* ADDED for many-many */
@Insert(onConflict = IGNORE)
fun insert(clothingSubCategoryMap: ClothingSubCategoryMap): Long
@Transaction
@Query("SELECT * FROM clothing")
fun getAllClothingWithSubCategories(): List<ClothingWithListOfSubCategories>
如果 activity 扩展为包括 :-
/* Added for many-many */
/* Note utilises clothing and sub-categories above */
dao.insert(ClothingSubCategoryMap(jeans,sc_popular))
dao.insert(ClothingSubCategoryMap(jeans,sc_swimwear))
dao.insert(ClothingSubCategoryMap(jeans,sc_shoes))
dao.insert(ClothingSubCategoryMap(anorak,sc_popular))
dao.insert(ClothingSubCategoryMap(anorak,sc_outerwear))
for(cwlsc: ClothingWithListOfSubCategories in dao.getAllClothingWithSubCategories()) {
Log.d("DBINFO","Name = ${cwlsc.clothing.name} Price is ${cwlsc.clothing.price} it is in ${cwlsc.subCategories.size} sub-categories. They are:-")
for(sc: SubCategory in cwlsc.subCategories) {
Log.d("DBINFO","\t${sc.subCategoryName}")
}
}
日志还将包括:-
D/DBINFO: Name = Jeans Price is 100.55 it is in 3 sub-categories. They are:-
D/DBINFO: Popular
D/DBINFO: Swimwear
D/DBINFO: Shoes
D/DBINFO: Name = Anorak Price is 214.55 it is in 2 sub-categories. They are:-
D/DBINFO: Popular
D/DBINFO: OuterWear
一定有更好的方法来做到这一点。我想创建一个包含我所有服装的数据库 table,并包含服装的子类别,如外衣、连衣裙、鞋子等。它们都将具有相同的属性(ID、名称、图像、关于、价格)。我不能创建一个 table 吗?我相信这是一个一对多的关系。
@Serializable
@Entity(tableName = CLOTHING_DATABASE_TABLE)
data class Clothing(
@PrimaryKey(autoGenerate = false)
val id: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = POPULAR_DATABASE_TABLE)
data class Popular(
@PrimaryKey(autoGenerate = false)
val popularId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = OUTERWEAR_DATABASE_TABLE)
data class Outerwear(
@PrimaryKey(autoGenerate = false)
val outerwearId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = TOPS_DATABASE_TABLE)
data class Tops(
@PrimaryKey(autoGenerate = false)
val topsId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = SWIMWEAR_DATABASE_TABLE)
data class Swimwear(
@PrimaryKey(autoGenerate = false)
val swimwearId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = SHOES_DATABASE_TABLE)
data class Shoes(
@PrimaryKey(autoGenerate = false)
val shoesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = BUNDLES_DATABASE_TABLE)
data class Bundles(
@PrimaryKey(autoGenerate = false)
val bundlesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = DRESSES_DATABASE_TABLE)
data class Dresses(
@PrimaryKey(autoGenerate = false)
val dressesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = PAJAMAS_DATABASE_TABLE)
data class Pajamas(
@PrimaryKey(autoGenerate = false)
val pajamasId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
@Serializable
@Entity(tableName = ACCESSORIES_DATABASE_TABLE)
data class Accessories(
@PrimaryKey(autoGenerate = false)
val accessoriesId: Int,
val name: String,
val image: String,
val about: String,
val price: String
)
您通常会有 2 或 3 个 table(3 个 many-many,即一件衣服可能有多个 sub-categories)。
对于 one-many 有一个 服装 table 其中有一列 sub-category 引用(相关)单个 sub-category 和一个 sub-category table 是根据唯一列(主键)引用的
对于many-many你有服装table(没有专栏参考单sub-category),sub-categorytable然后一个第三个 table 有两列,一列用于引用服装,另一列用于引用 sub-category,主键是两者的组合。
所以你可以:-
@Entity(tableName = CLOTHING_DATABASE_TABLE)
data class Clothing(
@PrimaryKey(autoGenerate = false)
val id: Long, /* should really be Long as */
val subCategoryReference: Long, /*<<<<< ADDED for the 1 subcategory */
val name: String,
val image: String,
val about: String,
val price: String
)
和:-
@Entity(tableName = SUBCATEGORY_DATABASE_TABLE)
data class SubCategory(
@PrimaryKey
val id: Long?,
val subCategoryName: String
)
- 要强制执行参照完整性,您可以将外键约束添加到服装的 subCategoryReference 列 table。
如果您想要一件 many-many,允许一件衣服有多个 sub-categories,那么您可以将第三个 table 作为 :-
@Entity(
tableName = CLOTHING_SUBCATEGORY_MAP_DATABASE_TABLE,
primaryKeys = ["clothingMap","subcategoryMap"],
)
data class ClothingSubCategoryMap(
val clothingMap: Long,
@ColumnInfo(index = true)
val subcategoryMap: Long
)
当然你可以有一件衣服 table 并且只有 sub-category 的一列。但是,这将被视为未规范化,因为您将在整个过程中复制 sub-category。
示例 1-many (即使用 2 tables 服装和子类别)
因为您很可能想要连同衣服一起检索 sub-category 那么您将拥有一个使用 @Embedded 和 @Relation 注释的 POJO,例如
data class ClothingWithSingleSubCategory (
@Embedded
val clothing: Clothing,
@Relation(
entity = SubCategory::class,
parentColumn = "subCategoryReference",
entityColumn = "id"
)
val subCategory: SubCategory
)
然后您可以将以下内容作为带注释的@Dao class :-
@Dao
interface AllDao {
@Insert(onConflict = IGNORE)
fun insert(clothing: Clothing): Long
@Insert(onConflict = IGNORE)
fun insert(subCategory: SubCategory): Long
@Transaction
@Query("SELECT * FROM clothing")
fun getAllClothingWithSubCategory(): List<ClothingWithSingleSubCategory>
}
使用 suitable @Database 注释 class 然后你可以在 activity:-
中有类似下面的内容class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val sc_popular = dao.insert(SubCategory(null,"Popular"))
val sc_outerwear = dao.insert(SubCategory(null,"OuterWear"))
val sc_tops = dao.insert(SubCategory(null,"Tops"))
val sc_swimwear = dao.insert(SubCategory(100,"Swimwear"))
val sc_shoes = dao.insert(SubCategory(null,"Shoes"))
val sc_dresses = dao.insert(SubCategory(null,"Dresses"))
val sc_pyjamas = dao.insert(SubCategory(null,"Pyjamas"))
dao.insert(Clothing(100200300400,sc_popular,"Jeans","jeans_image","blah","100.55"))
dao.insert(Clothing(100200300500,sc_outerwear,"Anorak","anorak_image","blah","214.55"))
for (cwsc: ClothingWithSingleSubCategory in dao.getAllClothingWithSubCategory()) {
Log.d("DBINFO","Name = ${cwsc.clothing.name} Price is ${cwsc.clothing.price} Sub-Category is ${cwsc.subCategory.subCategoryName}")
}
}
}
当 运行 日志将包括:-
D/DBINFO: Name = Jeans Price is 100.55 Sub-Category is Popular
D/DBINFO: Name = Anorak Price is 214.55 Sub-Category is OuterWear
示例many-many
与 1-many 一样,您需要一个 POJO,但它具有通过映射 table 获得的 sub-categories 列表。这使用 @Embeded 注释和 @Relation 注释,但扩展为包括 associateBy 以通知 Room 关于中间 table。所以你可以:-
data class ClothingWithListOfSubCategories(
@Embedded
val clothing: Clothing,
@Relation(
entity = SubCategory::class,
parentColumn = "id",
entityColumn = "id",
associateBy = Junction(
value = ClothingSubCategoryMap::class,
parentColumn = "clothingMap",
entityColumn = "subcategoryMap"
)
)
val subCategories: List<SubCategory>
)
您可以在带注释的@Dao 中包含以下内容 class:-
/* ADDED for many-many */
@Insert(onConflict = IGNORE)
fun insert(clothingSubCategoryMap: ClothingSubCategoryMap): Long
@Transaction
@Query("SELECT * FROM clothing")
fun getAllClothingWithSubCategories(): List<ClothingWithListOfSubCategories>
如果 activity 扩展为包括 :-
/* Added for many-many */
/* Note utilises clothing and sub-categories above */
dao.insert(ClothingSubCategoryMap(jeans,sc_popular))
dao.insert(ClothingSubCategoryMap(jeans,sc_swimwear))
dao.insert(ClothingSubCategoryMap(jeans,sc_shoes))
dao.insert(ClothingSubCategoryMap(anorak,sc_popular))
dao.insert(ClothingSubCategoryMap(anorak,sc_outerwear))
for(cwlsc: ClothingWithListOfSubCategories in dao.getAllClothingWithSubCategories()) {
Log.d("DBINFO","Name = ${cwlsc.clothing.name} Price is ${cwlsc.clothing.price} it is in ${cwlsc.subCategories.size} sub-categories. They are:-")
for(sc: SubCategory in cwlsc.subCategories) {
Log.d("DBINFO","\t${sc.subCategoryName}")
}
}
日志还将包括:-
D/DBINFO: Name = Jeans Price is 100.55 it is in 3 sub-categories. They are:-
D/DBINFO: Popular
D/DBINFO: Swimwear
D/DBINFO: Shoes
D/DBINFO: Name = Anorak Price is 214.55 it is in 2 sub-categories. They are:-
D/DBINFO: Popular
D/DBINFO: OuterWear