excilys/androidannotations — Issue #11: Compile time ORM
Author: pyricau
Created: 2012-01-06 10:36:12+00:00
State: open
Labels: Enhancement

Reported by project member py.ricau, Apr 14, 2011
Ok, this might sound silly / crazy... but what about using annotations to generate helpers at compile time for SQLite usage ? It could be a compile time JPA implementation, or maybe something completely different.

The first step might be to list all Android frameworks that provide solutions to hide the SQLite complexity.
Delete comment Comment 1 by mail.michael.ludwig, Apr 21, 2011
One framework I know is ORMlite. But i did not use it. But the idea is definetly very good
Delete comment Comment 2 by project member py.ricau, Jul 19, 2011
A StackOverflow question on the subject: http://stackoverflow.com/questions/371538/any-good-orm-tools-for-android-development

*******************

androidsql (defines schema with an enum) http://negentropiccoder.blogspot.com/2009/04/android-sqlite-framework-based-on-enum.html

*******************

orman (not specific to android): https://github.com/ahmetalpbalkan/orman/wiki

*******************

ormlite (not specific to android) : http://ormlite.com/

*******************

db4o (not specific to android) : http://developer.db4o.com/Blogs/Product/tabid/167/entryid/76/Default.aspx . Replaces SQLite.

*******************

ActiveAndroid: https://www.activeandroid.com/
Very interesting solution, but not free (only works on emulator). Mix between active record style (extending a base model class, which provides save and delete method) and annotations.

Queries are still a bit raw:

ActiveRecordBase.query(context, Item.class, new String[] { "Id", "Name"}, "Category = " + category.getId(), "Name ASC");

I don't like this kind of query methods with multiple weird and null parameters... and I don't like the unsafe strings (think Hibernate Metamodel generator).

*******************

android-active-record : http://code.google.com/p/android-active-record/

Works quite the same way as the previous framework (extending ActiveRecordBase), but free, less documented, and no annotation.

*******************

An interesting idea would be to generate the empty database at compile time, and inject it at first run (by coping and pasting the database file.

Delete comment Comment 3 by project member py.ricau, Jul 19, 2011
Querydsl (http://www.querydsl.com) uses annotation processing to generate a DSL dedicated to querying your entities, using JPA, SQL, and others.
Delete comment Comment 4 by project member py.ricau, Jul 19, 2011
Another list from StackOverflow: http://stackoverflow.com/questions/296587/light-weight-alternative-to-hibernate

Empire-DB : http://incubator.apache.org/empire-db/ One must generate a DDL, and them use a DSL a bit in the same way as Querydsl, but a lot more verbose.

Delete comment Comment 5 by project member py.ricau, Oct 20, 2011
(No comment was entered for this change.)
Labels: Milestone-
Delete comment Comment 7 by project member mat.boniface, Nov 21, 2011
IMHO, AA should not provide a "high level really complex way to manage data" like it's proposed in many ORMs (JSR 317 FR killed me). A lot of Android applications are really simple so it could be nice to bring a easy way to access data for developers.

What do you think about limiting AA features to dynamic finders ? And maybe a few more ?

I mean something like that :

public class MyActivity extends Activity {
@DAO
PlaceDAO placeDAO
...
}

@DAO
public abstract class PlaceDAO {

/**
* neighborhood is defined by developer as a field in the DB (table Place) and an attribute in the Place class. This method returns a list of Places that match with the given neighborhood name.
*/
public abstract List findPlace(String neighborhood);

/**
* Will return the first result of the request that returns a Place where id field value equal id parameter value. (We don't care about PK/FK, it's not the AA job)
*/
public abstract Place findPlace(int id);

/**
* Insert a new row into the Place table using the parameters (names and values).
*/
public abstract insertPlace(int id, int longitudeE6, int latitudeE6, String address);

/**
* Will update the row identified by id parameter by using the adress value.
*
public abstract updatePlaceSetAddress(int id, String adress);

@Transactional
public moreComplicatedMethodWrittenByDev() {
...
}

}

Here, all abstract methods are generated by AA, and the user can implements its "complicated" business method.

With this example I suppose that developers define himself the database schema.
Delete comment Comment 8 by project member py.ricau, Nov 21, 2011
Ok, interesting.

A few notes :

We should provide a way to access the db, from the abstract class and from the generated class. Should a connection be part of the methods parameters ? Should we allow some constructor parameters ? Should we define a standard method to "retrieve a connection" ? Or should we work at the db level, letting the user open connections ?

How would the Object > ContentValues mapping occur in "Place findPlace(int id);" ? Do you look at fields, getters / setters ? Do you need an empty constructor ? What contraints do we put on the entities ?

You said you don't care about FKs. So if Place has a list of Users, you just let that to null, right ?

What about joins and projections ?

I like the idea of concentrating on the finders, but that may not be so useful, would it ?

Should me provide a mapping method ? For example, if the users writes an abstract method "Place mapFromCursor(cursor)", we would implement it. And if he implements it, we would use that. What do you think ?

Maybe we should also generate a metamodel for the entities. Create the class Place_, that would hold static fields holding the fields names. That would allow the user to have type safety when writing requests.
Delete comment Comment 9 by project member py.ricau, Nov 21, 2011
Let's try to list what usual ORM can do, and then pick what we want (with implementation examples):

- Generates Entities from SQL DDL (some hibernate tools)
- Generates DDL from entities (hibernate)
- Row > Object mapping (hibernate)
- Session objects, with automagic updates of the db (hibernate)
- Create / update the database schema (hibernate, flyweight)
- Helpers for customs queries (Querydsl, hibernate metamodel generator)
- Dynamic finders for simple queries (Spring Data)
Delete comment Comment 10 by project member py.ricau, Nov 21, 2011
A few more :

- Handling FKs (OneToMany, ManyToOne, OneToOne, ManyToMany)
- Handling transactions

I think we probably don't want session management, because it adds a lot of complexity in the backend code, and the dev doesn't have a feeling of "being in control" (that's one of hibernate's best and worst feature, in my opinion...)

We may decide that we don't want to handle FKs, but then we have to define how the user should work with FKs.
Delete comment Comment 11 by project member py.ricau, Dec 29, 2011
Interesting comment in issue 40 :

**********************************************
Comment 4 by wblandin, Dec 26 (2 days ago)
If you take a loot at:
http://developer.android.com/resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html

You can that see a lot of this is boilerplate and can be deduced from:
http://developer.android.com/resources/samples/NotePad/src/com/example/android/notepad/NotePad.html

So annotations could take care of this.. A bit like Symfony2 (PHP framework)
http://symfony.com/doc/2.0/book/doctrine.html (search for "annotation")

What do you think?
**********************************************