Custom types allow entities to have properties of any type. By default greenDAO supports the following types:
1 2 3 4 5 6 7 8 9 10 | boolean, Boolean int, Integer short, Short long, Long float, Float double, Double byte, Byte byte[] String Date |
Convert annotation and property converter
To add support for a custom type, you can map them to one of the supported types using a @Convert annotation. You also need to provide a PropertyConverter implementation.
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | @Entity public class User { @Id private Long id; @Convert(converter = RoleConverter.class, columnType = Integer.class) private 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; } } } |
Note: if you define your custom type or converter inside your entity class, they have to be static.
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 not the SQLite types, but the primitive Java types offered by greenDAO. It is recommended to use a primitive type that is easily convertible (int, long, byte array, String, …).
Note: For optimal performance, greenDAO will use a single converter instance for all conversions. Make sure the converter does not have any other constructor besides the parameter-less default constructor. Also, make it thread safe, because it might be called concurrently on multiple entities.
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 type for queries (for example in WHERE arguments). Also note that operations done inside the database always refer to the primitive type, for example in ORDER BY clauses.
For example when building a query, you can use your property converter:
1 2 3 4 | RoleConverter converter = new RoleConverter(); List<User> authors = userDao.queryBuilder() .where(Properties.Role.eq(converter.convertToDatabaseValue(Role.AUTHOR))) .list(); |
In the section-“Joins”,i think there is an error with the example “self-join”:
If u want to find find all persons, whose grandfather’s name is “Lincoln”, should be:
QueryBuilder qb = personDao.queryBuilder();
Join father = qb.join(Properties.FatherId,Person.class);
Join grandfather = qb.join(father, Properties.FatherId, Person.class, Properties.Id);
grandfather.where(Properties.Name.eq(“Lincoln”));
List lincolnDescendants = qb.list();
not to be:
QueryBuilder qb = personDao.queryBuilder();
Join father = qb.join(Person.class, Properties.FatherId);
Join grandfather = qb.join(father, Properties.FatherId, Person.class, Properties.Id);
grandfather.where(Properties.Name.eq(“Lincoln”));
List lincolnDescendants = qb.list();
Please update your ref:
columnType seems now to be dbType !?
@rootandy: If you are referring to ObjectBox, check here: http://objectbox.io/documentation/custom-types/
sorry – i was somewhere else with my thoughts