How to use the legacy greenDAO generator to create entities and DAO files.
In most cases, we recommend to use the new Gradle plugin instead. However, some advanced features are currently only supported by the generator. For example multiple schemas.
Overview
To learn how to create entities you should have a look at the DaoExampleGenerator project. It contains a single class containing the data model definition in code:
1 2 3 4 5 6 7 8 9 | Schema schema = new Schema(1, "de.greenrobot.daoexample"); Entity note= schema.addEntity("Note"); note.addIdProperty(); note.addStringProperty("text").notNull(); note.addStringProperty("comment"); note.addDateProperty("date"); new DaoGenerator().generateAll(schema, "../DaoExample/src/main/java"); |
As you can see, you create a Schema object, to which you can add entities. An entity is a class tied to a database table. An entity contains properties, which are mapped to database columns.
Once the schema is completely defined, you can trigger the code generation. This is how the Note.java and NoteDao.java files from the DaoExample project where created.
Schema
Entities belong to a schema, so a schema is the first object you define. Call the constructor with the schema version and the default Java package:
1 | Schema schema = new Schema(1, "de.greenrobot.daoexample"); |
The default Java package is used when greenDAO generates entities, DAOs, and JUnit tests. If you want the DAO and test classes to go into separate packages, refine your schema like this:
1 2 3 4 | // DAO classes go into the "dao" package schema.setDefaultJavaPackageDao("de.greenrobot.daoexample.dao"); // test classes go into the "test" package schema.setDefaultJavaPackageTest("de.greenrobot.daoexample.test"); |
Finally, there are two optional flags to make entities active, and to turn on support for keep sections. Those features are not yet documented; have a look at the test project in the source code distribution.
1 2 3 4 | // optional: make entities active schema.enableActiveEntitiesByDefault(); // optional: enable KEEP section support schema.enableKeepSectionsByDefault(); |
Entities
Once you have a schema object you can add entities to it:
1 | Entity user = schema.addEntity("User"); |
An entity has several settings you can change, and more importantly, you can add properties to an entity:
1 2 3 4 | user.addIdProperty(); user.addStringProperty("name"); user.addStringProperty("password"); user.addIntProperty("yearOfBirth"); |
Custom types
To map a custom type to one of the supported property types, specify the custom type and a converter when adding a property:
1 2 | user.addLongProperty("creationTime") .customType("com.example.UserTimestamp", "com.example.UserTimestampConverter"); |
See Custom Types for further details.
Inheritance, Interfaces, and Serializable
Entities may inherit from another non-entity class:
1 2 | // class ExampleEntity extends BaseClass exampleEntity.setSuperclass("BaseClass"); |
Note: currently it is impossible to have another entity as a super class (there are no polymorphic queries either).
Often it is preferable to use interfaces as a common base for entity properties and behavior. For example, if entity A and B share a set of properties, these properties (their getters and setters) can be defined in interface C:
1 2 3 4 | // entity class A implements C entityA.implementsInterface("C"); // entity class B implements C entityB.implementsInterface("C"); |
There is a convenience method to make an entity inherit from Serializable:
1 2 | // class ExampleEntity implements Serializable exampleEntity.implementsSerializable(); |
Javadoc and annotations
You can add Javadoc documentation and Java annotations to entities:
1 2 3 | myEntity.setJavaDoc("This is an hell of an entity.\nIt represents foos and bars."); // add an annotation, though you can supply any string myEntity.setCodeBeforeClass("@Awesome"); |
Use \n to create a new line. The Javadoc string will automatically be wrapped in a proper Javadoc comment.
The same is possible for properties of entities, except that you can control it for fields, getters, and setters separately:
1 2 3 | myEntity.addIntProperty("counter") .codeBeforeField("@SerializedName(\"the-number-of-things\")") .javaDocGetterAndSetter("The total count"); |
The full list of methods offered by PropertyBuilder:
- codeBeforeField
- codeBeforeGetter
- codeBeforeGetterAndSetter
- codeBeforeSetter
- javaDocField
- javaDocGetter
- javaDocGetterAndSetter
- javaDocSetter
If you experience encoding issues (like when using a non-US-ASCII language like Chinese), double check your Gradle settings. Maybe you have to add the following line to your Gradle script:
1 | tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } |
Keep sections
Entity classes are overwritten on each generator run. So to add custom code to your enities use “KEEP” sections.
To enable them, call enableKeepSectionsByDefault() on the schema, or setHasKeepSections(true) on specific entities.
Once you run your generator again, three keep sections are generated inside the entities. Now, you can put your custom code between KEEP [...] and KEEP [...] END:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // KEEP INCLUDES - put your custom includes here import com.example.ExampleClass; // KEEP INCLUDES END ... // KEEP FIELDS - put your custom fields here private void ExampleClass someCustomField; // KEEP FIELDS END ... // KEEP METHODS - put your custom methods here public ExampleClass getCustomStuff() { ... } // KEEP METHODS END |
Do not modify the KEEP comments.
In any case, it is a good idea to backup or commit your custom code in case something goes wrong.
Relations
For an overview over relations, see Relations.
To-One relations (1:1)
To create a to-one relation to another entity (one entity object) add a property for the foreign key (id) value. Use the new property to add the relation:
1 2 3 4 | // add the foreign key "pictureId" to the "user" entity Property pictureIdProperty = user.addLongProperty("pictureId").getProperty(); // set up a to-one relation to the "picture" entity user.addToOne(picture, pictureIdProperty); |
The generated User entity will now have a Picture property (including getPicture() and setPicture()).
1 2 | Picture picA = user.getPicture(); user.setPicture(picB); |
See Modelling To-One Relations for further details.
Relation names and multiple relations
To add additional to-one relations to the same entity, they need to be named:
1 2 3 4 5 6 7 8 | // by default a to-one relation is named like the target entity // here it is automatically named "picture" Property pictureIdProperty = user.addLongProperty("pictureId").getProperty(); user.addToOne(picture, pictureIdProperty); // to add more to-one relations, they need to be named differently // so name this one "thumbnail" Property thumbnailIdProperty = user.addLongProperty("thumbnailId").getProperty(); user.addToOne(picture, thumbnailIdProperty, "thumbnail"); |
To-Many relations (1:N)
To add a to-many relation to a list of entities add a foreign key property to that entity, then set up the relation for your entity:
1 2 3 4 5 6 7 | // add customerId foreign key to the order entity Property customerId = order.addLongProperty("customerId").notNull().getProperty(); // set up a to-many relation to the orders entity from the customer entity ToMany customerToOrders = customer.addToMany(order, customerId); // optional: name the relation and specify the order of the referenced items customerToOrders.setName("orders"); customerToOrders.orderAsc(orderDate); |
See Resolving and Updating To-Many Relations for further details.
Bi-Directional 1:N Relations
Sometimes you want to navigate 1:N relations in both directions. In greenDAO, you have to add a to-one and a to-many relation to achieve this.
The following example shows the complete modelling of the customer and order entities, we used as an example before. This time, we use the customerId property for creating both relations:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Entity customer = schema.addEntity("Customer"); customer.addIdProperty(); customer.addStringProperty("name").notNull(); Entity order = schema.addEntity("Order"); order.setTableName("ORDERS"); // "ORDER" is a reserved keyword order.addIdProperty(); Property orderDate = order.addDateProperty("date").getProperty(); Property customerId = order.addLongProperty("customerId").notNull().getProperty(); order.addToOne(customer, customerId); ToMany customerToOrders = customer.addToMany(order, customerId); customerToOrders.setName("orders"); customerToOrders.orderAsc(orderDate); |
Let’s assume we have an order entity. Using both relations, we could get the customer and all orders the customer has ever made:
1 | List allOrdersOfCustomer = order.getCustomer().getOrders(); |
Many-to-Many Relations (N:M)
In databases, N:M relations are modeled using a join table. The join table holds entries having rows with foreign keys to each of the relating tables.
While the generator does not support N:M relations directly, you can model the join table as a separate entity. In practice, you often have “relation entities” with additional properties, so you might want to do so anyway.
greenDAO 3 has direct support for n:m relations.
Modelling Tree Relations (Example)
You can model a tree relation by modelling an entity having a to-one and a to-many relation pointing to itself:
1 2 3 4 5 | Entity treeEntity = schema.addEntity("TreeEntity"); treeEntity.addIdProperty(); Property parentIdProperty = treeEntity.addLongProperty("parentId").getProperty(); treeEntity.addToOne(treeEntity, parentIdProperty).setName("parent"); treeEntity.addToMany(treeEntity, parentIdProperty).setName("children"); |
The generated entity lets you navigate to its parent and children:
1 2 | TreeEntity parent = child.getParent(); List grandChildren = child.getChildren(); |
Triggering generation
Once your entity schema is in place, you can trigger the code generation process. In your generator project (a Java project having a static main() method) call:
1 2 | DaoGenerator daoGenerator = new DaoGenerator(); daoGenerator.generateAll(schema, "../DaoExample/src/main/java"); |
So, all you need is the schema object and a target directory, which is typically a source folder of your Android project.
To generate the test classes in a separate directory you can specify another directory as a third parameter to generateAll().
Note: If you have issues running the main() method in Android Studio (NoClassDefFoundError, ClassNotFoundException or TemplateNotFoundException), try running the generator using the Gradle application plugin. Configure the class with your main() method in your build.gradle file:
1 2 | apply plugin: 'application' mainClassName = "com.example.YourGeneratorClass" |
Then execute the Gradle run task.
More examples
Check out the DaoExampleGenerator project. Also, the DaoGenerator internal sub project may contain useful examples.