Custom Types
How to store types that are not built-in, recommendations for storing enums, and using property converters.
ObjectBox supports a wide range of built-in property types. For types that aren't directly supported, you can use converters to map them to a built-in type.
Flex property converters
In ObjectBox for Java/Kotlin, Flex properties use converters internally. You can exchange converters to fine-tune the conversion process. To override the default converter, use @Convert. For example to use another built-in FlexObjectConverter subclass:
// StringLongMapConverter restores any integers always as Long
@Convert(converter = StringLongMapConverter.class, dbType = byte[].class)
@Nullable Map<String, Object> stringMap;// StringLongMapConverter restores any integers always as Long
@Convert(converter = StringLongMapConverter::class, dbType = ByteArray::class)
var stringMap: MutableMap<String, Any>? = nullYou can also write a custom converter like shown below.
Convert annotation and property converter
To add support for a custom type, you need to provide a conversion to one of the ObjectBox built-in types. For example, you could define a color in your entity using a custom Color class and map it to an Integer. Or you can map the popular org.joda.time.DateTime from Joda Time to a Long.
Here is an example mapping an enum to an integer:
@Entity
public class User {
@Id
public long id;
@Convert(converter = RoleConverter.class, dbType = Integer.class)
public Role role;
public enum Role {
DEFAULT(0), AUTHOR(1), ADMIN(2);
final int id;
Role(int id) {
this.id = id;
}
}
public static class RoleConverter implements PropertyConverter<Role, Integer> {
@Override
public Role convertToEntityProperty(Integer databaseValue) {
if (databaseValue == null) {
return null;
}
for (Role role : Role.values()) {
if (role.id == databaseValue) {
return role;
}
}
return Role.DEFAULT;
}
@Override
public Integer convertToDatabaseValue(Role entityProperty) {
return entityProperty == null ? null : entityProperty.id;
}
}
}Things to look out for
If you define your custom type or converter inside a Java or Kotlin entity class, it must be static or respectively not an inner class.
Don’t forget to handle null values correctly – usually, you should return null if the input is null.
Database types in the sense of the converter are the primitive (built-in) types offered by ObjectBox, as mentioned in the beginning. It is recommended to use a primitive type that is easily convertible (int, long, byte array, String, …).
You must not interact with the database (such as using Box or BoxStore) inside the converter. The converter methods are called within a transaction, so for example, getting or putting entities to a box will fail.
List/Array types
You can use a converter with List types. For example, you could convert a List of Strings to a JSON array resulting in a single string for the database. At the moment it is not possible to use an array with converters (you can track this feature request).
How to convert Enums correctly
Enums are popular with data objects like entities. When persisting enums, there are a couple of best practices:
Do not persist the enum’s ordinal or name: Both are unstable, and can easily change the next time you edit your enum definitions.
Use stable ids: Define a custom property (integer or string) in your enum that is guaranteed to be stable. Use this for your persistence mapping.
Prepare for the unknown: Define an UNKNOWN enum value. It can serve to handle null or unknown values. This will allow you to handle cases like an old enum value getting removed without crashing your app.
Custom types in queries
QueryBuilder is unaware of custom types. You have to use the primitive DB type for queries.
So for the Role example above you would get users with the role of admin with the query condition .equal(UserProperties.Role, 2).
Last updated
Was this helpful?