Как вставить данные во многие для многих таблиц отношений и получить последний идентификатор В тех случаях, когда метод принимает два параметра? - PullRequest
0 голосов
/ 16 января 2020

Комната возвращает возвращенный идентификатор, когда вход имеет только один параметр

  @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertWithDrinks(item: DrinkFavourite): Long 

Как я могу получить идентификатор, когда метод выглядит следующим образом

 @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertWithDrinks(item: DrinkFavourite, List<Drink>)

Вернее, как сделать вы обрабатываете отношения «многие ко многим»? У меня есть отношения и таблица перекрестных ссылок, как эта


data class DrinkFavouritesWithDrinks(
    @Embedded
    val item: DrinkFavourite,
    @Relation(
        parentColumn = "item_id",
        entityColumn = "drink_id",
        associateBy = Junction(DrinkFavouriteAndDrinksCrossRef::class)
    )
    val drinks: List<Drink> = emptyList()
)

моя перекрестная ссылка

@Entity(
    primaryKeys = ["item_id", "drink_id"]
)
data class DrinkFavouriteAndDrinksCrossRef(
    @ColumnInfo(name = "item_id")
    val itemId: Long,
    @ColumnInfo(name = "drink_id")
    val drinkId: Int
) 

1 Ответ

0 голосов
/ 16 января 2020

Как я могу получить идентификатор, когда метод выглядит следующим образом

Когда вы вставляете несколько строк, вы получаете результирующие идентификаторы в Array<Long>

Однако для базовая таблица перекрестных ссылок / сопоставлений c, которую вы редко, когда-либо использовали бы в столбце rowid (возвращаемое значение).

  • rowid возвращается, даже если столбец неявно определен. То есть, за исключением редко используемых таблиц БЕЗ ROWID, все таблицы имеют скрытый столбец с именем rowid .

    • Когда вы используете INTEGER PRIMARY KEY для определения столбца, столбец является псевдонимом столбца rowid . В комнате @PrimaryKey для Long или Int, с или без autoGenerate = true/false (без = false) равняется INTEGER PRIMARY KEY или, если autoGenerate = true до INTEGER PRIMARY KEY AUTOINCREMENT.

Как вы относитесь ко многим ко многим отношениям?

Вот пример, основанный на доступном коде, с созданным другим кодом.

Таким образом, в дополнение к вашей сущности DrinkFavouriteAndDrinksCrossRef.

Сущности для DrinkFavourite и Item

@Entity
 data class DrinkFavourite(
    @PrimaryKey
    val drink_id: Int? = null,
    val drink_name: String = ""
)
@Entity

класс данных Drink (@PrimaryKey var itemId: Long ?, var itemName: String)

Dao AllDao : -

@Dao
interface AllDao {

    @Insert
    fun insertDrinkFavourite(drinkFavourite: DrinkFavourite) :Long

    @Insert
    fun insertManyDrinkFavourite(drinkFavourites: List<DrinkFavourite>) :Array<Long>

    @Insert
    fun insertItem(drink: Drink) :Long

    @Insert
    fun insertManyItems(drinks: List<Drink>) :Array<Long>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insertDrinkFavouriteAndDrinksCrossRef(drinkFavouriteAndDrinksCrossRef: DrinkFavouriteAndDrinksCrossRef) :Long

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insertManyDrinkFavouriteAndDrinksCrossRef(drinkFavouriteAndDrinksCrossRefs: List<DrinkFavouriteAndDrinksCrossRef>) :Array<Long>
}
  • Служит для вставки одной сущности / строки и множества сущностей / строк для каждой из 3 сущностей.

В следующих 3 вставках, определенных в Дао, для вставки 3 Drink с, 4 DrinkFavourite с и затем вставить 12 DrinkFavouriteAndDrinksCrossRef с (3 Drink * 4 DrinkFavorite) перестановок, то есть все возможные перестановки, на которые можно перейти, ссылаясь на основе вставленного идентификатора.

class MainActivity : AppCompatActivity() {

    lateinit var database: Database

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        database = Room.databaseBuilder(this, Database::class.java, "drinksdb")
            .allowMainThreadQueries()
            .build()
        //val firsItemtid = database.allDao().insertItem( Item(0,"X"))
        val manyItemIds = database.allDao().insertManyItems(
            listOf(
                Drink(null,"A"),
                Drink(null,"B"),
                Drink(null,"C")
            )
        )
        val manyDrinkFavouriteIds = database.allDao().insertManyDrinkFavourite(
            listOf(
                DrinkFavourite(null,"DrinkA"),
                DrinkFavourite(null,"DrinkB"),
                DrinkFavourite(null,"DrinkC"),
                DrinkFavourite(null,"DrinkD")
            )
        )

        var xrefcombos = ArrayList<DrinkFavouriteAndDrinksCrossRef>()
        for(itemId: Long in manyItemIds) {
            for (dfId: Long in manyDrinkFavouriteIds) {
                xrefcombos.add( DrinkFavouriteAndDrinksCrossRef(itemId,dfId.toInt()))
            }
        }
        val drinkFavouriteAndDrinksCrossRefIdList = database.allDao().insertManyDrinkFavouriteAndDrinksCrossRef(xrefcombos)
        for (dfadcrId in drinkFavouriteAndDrinksCrossRefIdList) {
            Log.d("DRKFAVDRNKXREF","Id = " + dfadcrId)
        }
    }
}

Вывод: -

2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 1
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 2
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 3
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 4
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 5
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 6
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 7
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 8
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 9
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 10
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 11
2020-01-17 07:46:40.621 D/DRKFAVDRNKXREF: Id = 12

т.е. были добавлены 12 перестановок.

Я не верю, что вы можете эффективно использовать @Insert делать что-то кроме вставок в соответствии с сущностью / объектом, который вставляется. Для более сложных вставок, основанных на других значениях, вы должны использовать @Query с подходящими SQL.

Дополнительные

В отношении: -

data class DrinkFavouritesWithDrinks(
    @Embedded
    val item: DrinkFavourite,
    @Relation(
        parentColumn = "item_id",
        entityColumn = "drink_id",
        associateBy = Junction(DrinkFavouriteAndDrinksCrossRef::class)
    )

I полагайте, что это должно быть: -

data class DrinkFavouriteWithDrinks (

    @Embedded
    val drinkFavourite: DrinkFavourite,
    @Relation(
        entity =  Drink::class,
        entityColumn = "itemId",
        parentColumn = "drink_id",
        associateBy = Junction(
            DrinkFavouriteAndDrinksCrossRef::class,entityColumn = "item_id",parentColumn = "drink_id"))
    val drinks: List<Drink> = emptyList()
    )
  • Вы получаете все напитки за DrinkFavourite, поэтому лучше использовать единственное, а не множественное число.
  • ассоциация должна знать столбцы

Вы могли бы иметь метод Дао, такой как: -

@Query("SELECT * FROM drinkfavourite")
fun getAllDrinkFavouritesWithDrinks() :List<DrinkFavouriteWithDrinks>

Добавление к следующему MainActivity выше: -

    val drinkFavouriteWithDrinksList = database.allDao().getAllDrinkFavouritesWithDrinks()
    var sb = StringBuilder()
    for (dfwd: DrinkFavouriteWithDrinks in drinkFavouriteWithDrinksList) {
        sb.clear().append("DrinkFavourite = ").append(dfwd.drinkFavourite)
        for (d: Drink in dfwd.drinks) {
            sb.append("\n\tDrink = ").append(d.itemName)
        }
        Log.d("DRINKFAVINFO", sb.toString())
    }

Результаты: -

2020-01-17 11:39:52.762 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=1, drinkFavouriteName=DrinkA)
      Drink = A
      Drink = B
      Drink = C
2020-01-17 11:39:52.763 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=2, drinkFavouriteName=DrinkB)
      Drink = A
      Drink = B
      Drink = C
2020-01-17 11:39:52.763 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=3, drinkFavouriteName=DrinkC)
      Drink = A
      Drink = B
      Drink = C
2020-01-17 11:39:52.763 D/DRINKFAVINFO: DrinkFavourite = DrinkFavourite(drink_id=4, drinkFavouriteName=DrinkD)
      Drink = A
      Drink = B
      Drink = C
  • Не лучший пример, поскольку каждый DrinkFavourite имеет все три напитка
...