在房间 android 中插入关系
Insert relation in Room android
我对如何在房间中插入关系有疑问。所以,我有 Product
和 ProductsList
实体。 ProductsList 可能有很多产品,但产品不应该知道它们包含在何处的列表。
@Entity(tableName = "products")
data class Product(
@PrimaryKey(autoGenerate = true)
val productId: Long,
val productName: String
)
@Entity
data class ProductList(
@PrimaryKey(autoGenerate = true)
val productListId: Long,
val listName: String
)
我创建了 ProductsListWithProducts class:
data class ProductListWithProducts(
@Embedded
val productList: ProductList,
@Relation(
parentColumn = "productListId",
entityColumn = "productId",
entity = Product::class
)
val productsId: List<Product>
)
但我不明白如何在数据库中插入数据。例如,我已经在它的 table 中添加了 Products
,然后它想创建新的 ProductList
。我检查了其他答案,发现它只是使用 Dao 来插入它,比如:
@Dao
abstract class ProductListDao {
@Transaction
fun insert(productList: ProductList, products: List<Product>) {
insert(productList)
for (product in products) {
insert(product)
}
}
但我不知道如何在这个 table 之间添加关系,因为我不想在产品实体中使用外键(因为在这种情况下我需要创建多对多关系).我考虑过其他实体
@Entity(primaryKeys = ["productId", "productListId"])
data class ProductListProducts(
val productId: Long,
val productListId: Long
)
但它也用于定义多对多关系。
我可以添加这个关系而不创建多对多关系,只创建一对多吗?
有 ProductListProducts 但是您可能希望考虑使用 :-
@Entity(
primaryKeys = ["productId", "productListId"]
,indices = [
Index(value = ["productListId"]) /* Index else Room warns */
]
/* Foreign Keys are optional BUT enforce referential integrity */
, foreignKeys = [
ForeignKey(
entity = Product::class,
parentColumns = ["productId"],
childColumns = ["productId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = ProductList::class,
parentColumns = ["productListId"],
childColumns = ["productListId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
]
)
data class ProductListProducts(
val productId: Long,
val productListId: Long
)
这是一个关联 table(参考table、映射table和许多其他术语)。因此,您使用的关系利用 association 作为 ProductList 和 Product 之间的 Junction。因此,您的 ProductListWithProducts POJO 变为:-
data class ProductListWithProducts (
@Embedded
val productList: ProductList,
@Relation(
entity = Product::class,
parentColumn = "productListId",
entityColumn = "productId",
associateBy = Junction(
ProductListProducts::class,
parentColumn = "productListId",
entityColumn = "productId"
)
)
val product: List<Product>
)
演示 使用上述 classes(以及您的 classes,其中 id 已更改为 Long=0
)
有道class喜欢:-
@Dao
abstract class AllDao {
@Insert
abstract fun insert(product: Product): Long
@Insert
abstract fun insert(productList: ProductList): Long
@Insert
abstract fun insert(productListProducts: ProductListProducts): Long
@Transaction
@Query("SELECT * FROM ProductList")
abstract fun getProductListWithProducts(): List<ProductListWithProducts>
}
然后是下面的(运行 在主线程上 brevity/convenience):-
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
var p1 = dao.insert(Product( productName = "Product1"))
var p2 = dao.insert(Product(productName = "Product2"))
var pl1 = dao.insert(ProductList(listName = "List1"))
var pl2 = dao.insert(ProductList(listName = "List2"))
dao.insert(ProductListProducts(p1,pl1))
dao.insert(ProductListProducts(p1,pl2))
dao.insert(ProductListProducts(p2,pl1))
dao.insert(ProductListProducts(dao.insert(Product(productName = "Product3")),dao.insert(
ProductList(listName = "List3")))
)
for(plwp: ProductListWithProducts in dao.getProductListWithProducts()) {
Log.d(TAG,"ProductList is ${plwp.productList.listName} ID is ${plwp.productList.productListId}")
for(p: Product in plwp.product) {
Log.d(TAG,"\t Product is ${p.productName} ID is ${p.productId}")
}
}
结果日志中包含:-
D/DBINFO: ProductList is List1 ID is 1
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: ProductList is List2 ID is 2
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: ProductList is List3 ID is 3
D/DBINFO: Product is Product3 ID is 3
Can I add this relation without creating many-to-many relation, just one-to-many?
以上(即关联 table)将处理 1 到多,但如果您不想要额外的 table,则必须包含 [=69 的标识符=] 在 child 中。您可以在关联 table 中强制执行一对多,方法是使 1 的列唯一。
至于你说的Mass类型插入
For example I already added Products in its table and after it want to create new ProductList
那么你也许可以通过以下额外的@Dao 来解决问题:-
@Insert
abstract fun insert(productListList: List<ProductList>): LongArray
@Insert
abstract fun insertManyProductListProducts(productListProductsList: List<ProductListProducts>): LongArray
/* This can be used to get a specific product or products according to a pattern */
/* e.g. */
/* if productPatterName is product1 then an exact match */
/* if prod% then all that start with prod */
/* if %prod all that end in prod */
/* if %prod% then all that have prod anywhere */
@Query("SELECT productId FROM products WHERE productName LIKE :productNamePattern")
abstract fun getProductIdByName(productNamePattern: String): LongArray
然后有代码如:-
/* Adding many new ProductLists to existing Products */
/* 1 add the new ProductLists */
/* Noting that the insert returns an array of the productListId's inserted */
val insertedProductLists = dao.insert(
listOf(
ProductList(listName = "ListX1"),
ProductList(listName = "ListX2")
)
)
/* 2. Determine the Product(s) that will be related to the new list of ProductLists */
val productIdList = dao.getProductIdByName("Product%") /* All products */
/* 3. Prepare the List of ProductListProducts for mass insertion */
val plplist: ArrayList<ProductListProducts> = ArrayList()
for(pid: Long in productIdList) {
for(plid: Long in insertedProductLists) {
plplist.add(ProductListProducts(pid,plid))
}
}
/* 4. add the relationships */
dao.insertManyProductListProducts(plplist)
- 如果您想要 1 个现有产品,例如product1 那么你就用
dao.getProductIdByName("Product1")
,当然你也可以increase/reduceArray中的productLists来适应。
这将导致:-
D/DBINFO: ProductList is List1 ID is 1
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: ProductList is List2 ID is 2
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: ProductList is List3 ID is 3
D/DBINFO: Product is Product3 ID is 3
D/DBINFO: ProductList is ListX1 ID is 4
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: Product is Product3 ID is 3
D/DBINFO: ProductList is ListX2 ID is 5
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: Product is Product3 ID is 3
我对如何在房间中插入关系有疑问。所以,我有 Product
和 ProductsList
实体。 ProductsList 可能有很多产品,但产品不应该知道它们包含在何处的列表。
@Entity(tableName = "products")
data class Product(
@PrimaryKey(autoGenerate = true)
val productId: Long,
val productName: String
)
@Entity
data class ProductList(
@PrimaryKey(autoGenerate = true)
val productListId: Long,
val listName: String
)
我创建了 ProductsListWithProducts class:
data class ProductListWithProducts(
@Embedded
val productList: ProductList,
@Relation(
parentColumn = "productListId",
entityColumn = "productId",
entity = Product::class
)
val productsId: List<Product>
)
但我不明白如何在数据库中插入数据。例如,我已经在它的 table 中添加了 Products
,然后它想创建新的 ProductList
。我检查了其他答案,发现它只是使用 Dao 来插入它,比如:
@Dao
abstract class ProductListDao {
@Transaction
fun insert(productList: ProductList, products: List<Product>) {
insert(productList)
for (product in products) {
insert(product)
}
}
但我不知道如何在这个 table 之间添加关系,因为我不想在产品实体中使用外键(因为在这种情况下我需要创建多对多关系).我考虑过其他实体
@Entity(primaryKeys = ["productId", "productListId"])
data class ProductListProducts(
val productId: Long,
val productListId: Long
)
但它也用于定义多对多关系。
我可以添加这个关系而不创建多对多关系,只创建一对多吗?
有 ProductListProducts 但是您可能希望考虑使用 :-
@Entity(
primaryKeys = ["productId", "productListId"]
,indices = [
Index(value = ["productListId"]) /* Index else Room warns */
]
/* Foreign Keys are optional BUT enforce referential integrity */
, foreignKeys = [
ForeignKey(
entity = Product::class,
parentColumns = ["productId"],
childColumns = ["productId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = ProductList::class,
parentColumns = ["productListId"],
childColumns = ["productListId"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
]
)
data class ProductListProducts(
val productId: Long,
val productListId: Long
)
这是一个关联 table(参考table、映射table和许多其他术语)。因此,您使用的关系利用 association 作为 ProductList 和 Product 之间的 Junction。因此,您的 ProductListWithProducts POJO 变为:-
data class ProductListWithProducts (
@Embedded
val productList: ProductList,
@Relation(
entity = Product::class,
parentColumn = "productListId",
entityColumn = "productId",
associateBy = Junction(
ProductListProducts::class,
parentColumn = "productListId",
entityColumn = "productId"
)
)
val product: List<Product>
)
演示 使用上述 classes(以及您的 classes,其中 id 已更改为 Long=0
)
有道class喜欢:-
@Dao
abstract class AllDao {
@Insert
abstract fun insert(product: Product): Long
@Insert
abstract fun insert(productList: ProductList): Long
@Insert
abstract fun insert(productListProducts: ProductListProducts): Long
@Transaction
@Query("SELECT * FROM ProductList")
abstract fun getProductListWithProducts(): List<ProductListWithProducts>
}
然后是下面的(运行 在主线程上 brevity/convenience):-
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
var p1 = dao.insert(Product( productName = "Product1"))
var p2 = dao.insert(Product(productName = "Product2"))
var pl1 = dao.insert(ProductList(listName = "List1"))
var pl2 = dao.insert(ProductList(listName = "List2"))
dao.insert(ProductListProducts(p1,pl1))
dao.insert(ProductListProducts(p1,pl2))
dao.insert(ProductListProducts(p2,pl1))
dao.insert(ProductListProducts(dao.insert(Product(productName = "Product3")),dao.insert(
ProductList(listName = "List3")))
)
for(plwp: ProductListWithProducts in dao.getProductListWithProducts()) {
Log.d(TAG,"ProductList is ${plwp.productList.listName} ID is ${plwp.productList.productListId}")
for(p: Product in plwp.product) {
Log.d(TAG,"\t Product is ${p.productName} ID is ${p.productId}")
}
}
结果日志中包含:-
D/DBINFO: ProductList is List1 ID is 1
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: ProductList is List2 ID is 2
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: ProductList is List3 ID is 3
D/DBINFO: Product is Product3 ID is 3
Can I add this relation without creating many-to-many relation, just one-to-many?
以上(即关联 table)将处理 1 到多,但如果您不想要额外的 table,则必须包含 [=69 的标识符=] 在 child 中。您可以在关联 table 中强制执行一对多,方法是使 1 的列唯一。
至于你说的Mass类型插入
For example I already added Products in its table and after it want to create new ProductList
那么你也许可以通过以下额外的@Dao 来解决问题:-
@Insert
abstract fun insert(productListList: List<ProductList>): LongArray
@Insert
abstract fun insertManyProductListProducts(productListProductsList: List<ProductListProducts>): LongArray
/* This can be used to get a specific product or products according to a pattern */
/* e.g. */
/* if productPatterName is product1 then an exact match */
/* if prod% then all that start with prod */
/* if %prod all that end in prod */
/* if %prod% then all that have prod anywhere */
@Query("SELECT productId FROM products WHERE productName LIKE :productNamePattern")
abstract fun getProductIdByName(productNamePattern: String): LongArray
然后有代码如:-
/* Adding many new ProductLists to existing Products */
/* 1 add the new ProductLists */
/* Noting that the insert returns an array of the productListId's inserted */
val insertedProductLists = dao.insert(
listOf(
ProductList(listName = "ListX1"),
ProductList(listName = "ListX2")
)
)
/* 2. Determine the Product(s) that will be related to the new list of ProductLists */
val productIdList = dao.getProductIdByName("Product%") /* All products */
/* 3. Prepare the List of ProductListProducts for mass insertion */
val plplist: ArrayList<ProductListProducts> = ArrayList()
for(pid: Long in productIdList) {
for(plid: Long in insertedProductLists) {
plplist.add(ProductListProducts(pid,plid))
}
}
/* 4. add the relationships */
dao.insertManyProductListProducts(plplist)
- 如果您想要 1 个现有产品,例如product1 那么你就用
dao.getProductIdByName("Product1")
,当然你也可以increase/reduceArray中的productLists来适应。
这将导致:-
D/DBINFO: ProductList is List1 ID is 1
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: ProductList is List2 ID is 2
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: ProductList is List3 ID is 3
D/DBINFO: Product is Product3 ID is 3
D/DBINFO: ProductList is ListX1 ID is 4
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: Product is Product3 ID is 3
D/DBINFO: ProductList is ListX2 ID is 5
D/DBINFO: Product is Product1 ID is 1
D/DBINFO: Product is Product2 ID is 2
D/DBINFO: Product is Product3 ID is 3