pardom/ollie — pull request #16 by iainconnor (2014-10-20 20:54:10+00:00)
Title: Adding ability for a single Cursor to contain multiple nested relationships.

Let me start by explaining the "issue" with all Android ORMs that I've seen so far, and the solutions I can think of, one of which this request is an attempt to implement.

So, if you have a model `User` which includes a relationship to another model `Image`...

``` java
@Table("users")
public class User extends Model {
@Column("name")
public String name;

@Column("avatar")
public Image avatar;
}

@Table("images")
public class Image extends Model {
@Column("url")
public String url;
}
```

... and you fetch a particular `User`, you also need some way of accessing the `Image` for that row. When you're fetching an individual element, this isn't really a big problem. However, if you're using a `ContentProvider` with a `CursorAdapter` and a `ListView`, for example, on every row the view loads, an additional database query executes (on the UI Thread) to load the associated `Image`. Once you get to a non-trivial schema, this can cause significant lag in your app.

The two ways I see of working around this are;

1. You attempt to flatten your model hierarchy by dropping the `Image` model entirely and just add an `avatar_url` column to the `User` model. In this example, this probably isn't a terrible option, but its an overly simple example.
2. You make it so that the Cursor includes not only the information for the `User`, but also the information for the `Image` associated with that user.

The second option is what this PR attempts.

Some more code should, I hope, show my solution. When you're querying this schema, hoping to get `User`s, you would also join on the `Image` for each of those users...

``` java
new Select("users.*, images.url as images_url, images._id as images__id").from(User.class).join(Image.class).on("users.image = images._id");
```

... note that we've also pulled out the columns for the `Image` for that `User`, and the names for those columns follow a pattern of `{table}_{column}`. Now we annotate that column in the `User` model to tell it to look in the `Cursor` for the associate `Image`....

``` java
@InCursor
@Column("image")
public Image image;
```

... the `@InCursor` annotation takes a class that tells it how to resolve the name for this model's columns in the `Cursor`. The default implementation follows that `{table}_{column}` pattern.

Now, if you take a look at the `User$$ModelAdapter` that gets generated, you'll see it inspects the `Cursor` for those relationship's columns without performing additional queries...

```java
public final void load(User entity, Cursor cursor, CursorNameResolver cursorNameResolver) {
// Other loaded values omitted for brevity.
Image image = new Image();
Image$$ModelAdapter imageAdapter = new Image$$ModelAdapter();
imageAdapter.load(image, cursor, (cursorNameResolver == null ? new ollie.cursor_name_resolver.UnderscoreCursorNameResolver() : cursorNameResolver));
entity.setImage(image);
}
```

Thanks again for the hard work and let me know what you think of adding such a feature. I'll be honest, the implementation didn't come out quite as clean as I would have liked, but I think the pattern shows some promise.