Возможен ли запрос с использованием составного первичного ключа с помощью Room?
@Entity(
tableName = "market_cap",
primaryKeys = ["assetId", "timestamp"]
)
data class MarketCapDataEntity(
val assetId: String,
val timestamp: Long,
val price: Double
)
Допустим, я хочу выполнить запрос по первичному ключу, как показано ниже?
@Query("SELECT * FROM market_cap WHERE primaryKeys = :compositeKey")
suspend fun getMarketCapByAssetId(compositeKey: String): List<MarketCapDataEntity>
Вам необходимо указать каждый компонент первичного ключа в вашем SQL-запросе, а не пытаться использовать один составной ключ.
@Entity(
tableName = "market_cap",
primaryKeys = ["assetId", "timestamp"]
)
data class MarketCapDataEntity(
val assetId: String,
val timestamp: Long,
val price: Double
)
@Dao
interface MarketCapDao {
@Query("SELECT * FROM market_cap WHERE assetId = :assetId AND timestamp = :timestamp")
suspend fun getMarketCapByAssetIdAndTimestamp(assetId: String, timestamp: Long): MarketCapDataEntity?
}
В Room нет специального свойства или параметра, который можно использовать для прямого указания составных первичных ключей как единого объекта в запросах. Каждый компонент составного первичного ключа необходимо указывать в SQL-запросе индивидуально.
Возможен ли запрос с использованием составного первичного ключа с помощью Room?
Нет (см. ниже), НО это то, что вы могли бы/не могли бы запросить.
По сути, цель индекса состоит в том, чтобы базовая система (оптимизатор запросов) оптимально выполняла поиск в базе данных.
Таким образом, вы никогда не запрашиваете индекс по индексу, а по столбцам, которые могут или не могут быть частью индекса.
Таким образом, для @Query
вы просто указываете столбец(и) для запроса. Не существует единого представления составного индекса, которое можно было бы использовать.
Таким образом, @Query("SELECT * FROM market_cap WHERE primaryKeys = :compositeKey")
приведет к ошибке, поскольку PrimaryKeys будет считаться именем столбца, которого не существует.
Вместо этого вы должны использовать что-то вроде: -
@Query("SELECT * FROM market_cap WHERE assetId = :assetId AND timestamp = :timestamp")
@Entity
, будут таблицами ROWID). В некоторых случаях это вполне может быть оптимальным индексом, поскольку SQLite написан с учетом идентификатора строки, обработка которого может быть в два раза быстрее, чем других индексов. Вы можете найти https://sqlite.org/rowidtable.html полезным.Удобная аннотация и первичный ключ(и)
Следует отметить, что некоторые удобные аннотации, например @Update
и @Delete
, действительно используют и требуют значений поля или полей, из которых состоит первичный ключ.
Поэтому, когда/если используется любой из них, важно, чтобы объект, переданный в аннотированную функцию/метод, имел значения полей первичного ключа, установленные в соответствующие значения (отмечая, что вы не можете обновлять значения первичного ключа, поскольку тогда это не позволит найти строку) .
@Query
с соответствующим SQL, например.@Query("UPDATE market_cap SET assetId=:newAssetId, timestamp=:newTimeStamp WHERE assetId=:originalAssetId AND timestamp=originalTimeStamp")
Я понимаю, но неужели для
primaryKeys
нет специального свойства?