Repository navigation
Store Map values as Long instead of Int #1181
Description
Activity
Tried to workaround it by implementing:
val mapping = mutableMapOf( "key1" to mutableMapOf( "subkey1" to 1L, "subkey2" to 1L, "subkey3" to 1L ), "key2" to mutableMapOf( "subkey4" to 1L ) )
and
@Entity data class MyDataClass( @Id var id: Long = 0, var mapping: MutableMap<String, MutableMap<String, Long>? = null )
however, ObjectBox still stores
LongasInteger.Thanks for this great issue! This behavior is due to ObjectBox using a
FlexObjectConvertersubclass by default for these "flex" properties, see their discussion in the docs, notably the converter class documentation.As you hinted at, try to override this with a specific converter. The built-in
StringLongMapConvertershould do what you want:@Convert(converter = StringLongMapConverter::class, dbType = ByteArray::class) var mapping: MutableMap<String, Any>? = null
Note: labeled this issue with "more info required" so it will auto-close in a few days if there are no follow-up comments.
Edit: also added this as an example in the docs linked above.
- addedmore info requiredFurther information is requestedFurther information is requested
on Jul 3, 2024 I've tried
@Convert(converter = StringLongMapConverter::class, dbType = ByteArray::class) var mapping: MutableMap<String, Any>? = null
however, the retrieved type from the database is still
Integerinstead ofLong.
Steps to reproduce
- Have the entity:
import io.objectbox.annotation.Convert import io.objectbox.annotation.Id import io.objectbox.converter.StringLongMapConverter @Entity data class MyDataClass( @Id var id: Long = 0, @Convert(converter = StringLongMapConverter::class, dbType = ByteArray::class) var mapping: MutableMap<String, Any>? = null )
- Have the mock data generation source:
class MockDataSource { fun generateData(): List<MyDataClass> { val mappingOne = mutableMapOf( "key1" to mutableMapOf( "subkey1" to 1L, "subkey2" to 1L, "subkey3" to 1L ), "key2" to 1L ) val mappingTwo = mutableMapOf( "key1" to mutableMapOf( "subkey1" to 2L, "subkey2" to 2L, "subkey3" to 2L ), "key2" to 2L ) val mappingThree = mutableMapOf( "key1" to mutableMapOf( "subkey1" to 3L, "subkey2" to 3L, "subkey3" to 3L ), "key2" to 3L ) val mappingsList = listOf( MyDataClass( mapping = mappingOne ), MyDataClass( mapping = mappingTwo ), MyDataClass( mapping = mappingThree ) ) return mappingsList } }
- Test:
fun `test MyDataClass`() { val mappingsList = MockDataSource().generateData() /** Insert test mappings into the database */ boxStore.boxFor<MyDataClass>().put(mappingsList) <get query from database> assertEquals(mappingsList, queryResult) }
I've left out
<get query from database>since in my case it's convoluted (since it's Android with Jetpack Compose, I implement a repository and order based on fieldtimestampand return aflow- it'll be too long to write it here).Please note this is with ObjectBox v3.8.0 in Android using Kotlin
- removedmore info requiredFurther information is requestedFurther information is requested
on Jul 4, 2024 I've tried the converter using the second layout and it worked.
Additionally, what's strange, is that with:
var mapping: MutableMap<String, Long>? = null
ObjectBox will correctly return a
Longand not anIntegerThanks! Did you by chance debug this and verified that the converter actually restores as
Long? E.g. it hits this line:
objectbox-java/objectbox-java/src/main/java/io/objectbox/converter/FlexObjectConverter.java
Line 290 in 289cc2c
resultMap.put(key, value.asLong()); I'll try to reproduce this once I have time. Maybe this is a Kotlin thing.
- addedmore info requiredFurther information is requestedFurther information is requested
on Jul 8, 2024 - removedmore info requiredFurther information is requestedFurther information is requested
on Jul 9, 2024 I've only ran the test with debugger by setting a breakpoint on the
assertline and verifying the type of the values returned by the mock data source against the ones returned by the database query call.Reacted by Uwe (ObjectBox)We tried to reproduce this and using the converter I suggested works.
Edit: I also added flex properties to the supported types list with a strong hint to read the documentation about limitations.
Note: labeled this issue with "more info required" so it will auto-close in a few days if there are no follow-up comments.
- addedmore info requiredFurther information is requestedFurther information is requesteddocumentationImprovements or additions to documentationImprovements or additions to documentationand removedenhancementNew feature or requestNew feature or request
on Jul 24, 2024 - removedmore info requiredFurther information is requestedFurther information is requested
on Jul 25, 2024
Is there an existing issue?
Use case
I am storing a mapping:
that is represented in the
data classas follows:ObjectBox will store the Long values as Ints due to not being wide enough. These breaks use cases where we do want to store the Long values as Long and not as Ints (for example test cases that use the same generated mock data to store in the database and to test against).
Proposed solution
Have an annotation that tells ObjectBox to store Long values as Long.
Alternatives
Tried using a
PropertyConverterhowever this breaks for the mapping I've provided.Additional context
Kotlin
Android