Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return type for Android Room joins

Let's say I want to do an INNER JOIN between two entities Foo and Bar:

@Query("SELECT * FROM Foo INNER JOIN Bar ON Foo.bar = Bar.id") List<FooAndBar> findAllFooAndBar(); 

Is it possible to force a return type like this?

public class FooAndBar {     Foo foo;     Bar bar; } 

When I try to do that, I get this error:

error: Cannot figure out how to read this field from a cursor. 

I've also tried aliasing the table names to match the field names, but that didn't work either.

If this isn't possible, how should I cleanly construct a compatible return type that includes all fields for both entities?

like image 748
pqvst Avatar asked Jul 12 '17 14:07

pqvst


People also ask

What is Dao in room?

android.arch.persistence.room.Dao. Marks the class as a Data Access Object. Data Access Objects are the main classes where you define your database interactions. They can include a variety of query methods. The class marked with @Dao should either be an interface or an abstract class.

Is Android room an ORM?

Room is an ORM, Object Relational Mapping library.

What is embedded in Room Android?

Marks a field of an Entity or POJO to allow nested fields (i.e. fields of the annotated field's class) to be referenced directly in the SQL queries. If the container is an Entity , these sub fields will be columns in the Entity 's database table.


2 Answers

Dao

@Query("SELECT * FROM Foo") List<FooAndBar> findAllFooAndBar(); 

Class FooAndBar

public class FooAndBar {     @Embedded     Foo foo;      @Relation(parentColumn =  "Foo.bar_id", entityColumn = "Bar.id")     List<Bar> bar;     // If we are sure it returns only one entry     // Bar bar;      //Getter and setter... } 

This solution seems to work, but I'm not very proud of it. What do you think about it?

Edit: Another solution

Dao, I prefer to explicitly select but "*" will do the job :)

@Query("SELECT Foo.*, Bar.* FROM Foo INNER JOIN Bar ON Foo.bar = Bar.id") List<FooAndBar> findAllFooAndBar(); 

Class FooAndBar

public class FooAndBar {     @Embedded     Foo foo;      @Embedded     Bar bar;      //Getter and setter... } 

edit: since Version 2.2.0-alpha01, room @Relation annotation can manage One-To-One relation

like image 93
Gaëtan S Avatar answered Oct 02 '22 20:10

Gaëtan S


Another option is to just write a new POJO representing the resulting structure of your JOIN query (which even supports column renaming to avoid clashes):

@Dao public interface FooBarDao {    @Query("SELECT foo.field1 AS unique1, bar.field1 AS unique2 "           + "FROM Foo INNER JOIN Bar ON Foo.bar = Bar.id")    public List<FooBar> getFooBars();     static class FooBar {        public String unique1;        public String unique2;    } }     

See: room/accessing-data.html#query-multiple-tables

like image 23
charles-allen Avatar answered Oct 02 '22 20:10

charles-allen