2017-07-12 41 views
8

Hãy nói rằng tôi muốn làm một INNER JOIN giữa hai thực thể FooBar:Return cho Phòng Android gia nhập

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

Có thể buộc một kiểu trả về như thế này?

public class FooAndBar { 
    Foo foo; 
    Bar bar; 
} 

Khi tôi cố gắng để làm điều đó, tôi nhận được lỗi này:

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

Tôi cũng đã thử aliasing tên bảng để phù hợp với tên trường, nhưng điều đó không làm việc, hoặc.

Nếu điều này là không thể, làm cách nào tôi nên xây dựng một kiểu trả về tương thích bao gồm tất cả các trường cho cả hai thực thể?

Trả lời

1

Is it possible to force a return type like this?

Bạn có thể thử @Embedded chú thích trên foobar. Điều đó sẽ yêu cầu Phòng cố gắng lấy các cột từ truy vấn của bạn và đổ chúng vào các trường hợp foobar. Tôi chỉ thử điều này với các thực thể, nhưng các tài liệu chỉ ra rằng nó cũng làm việc với các POJO.

Tuy nhiên, điều này có thể không hoạt động tốt nếu hai bảng của bạn có cột có cùng tên.

+0

Vâng, điều đó không làm việc kể từ khi đơn vị của tôi có cột có cùng tên (như 'id') ... – pqvst

+0

@pqvst: "làm thế nào tôi nên sạch sẽ xây dựng một tương thích loại trả về bao gồm tất cả các trường cho cả hai thực thể? " - hoặc chọn 'foo' hoặc' bar' thành '@ Embedded' và đặt các trường còn lại trực tiếp trong' FooAndBar' hoặc đặt tất cả các trường trực tiếp trong 'FooAndBar'. Sử dụng 'AS' trong SQL để đổi tên các cột trùng lặp trong tập hợp kết quả, và sử dụng' @ ColumnInfo' khi cần để ánh xạ các cột 'AS' được đổi tên thành những gì bạn muốn các trường được. – CommonsWare

+0

Đó chính là điều tôi muốn tránh phải làm ...Không cảm thấy rất "sạch" đối với tôi:/ – pqvst

8

Đào

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

Lớp FooAndBar

public class FooAndBar { 
     @Embedded 
     Foo foo; 

     @Relation(parentColumn = "Foo.bar_id", entityColumn = "Bar.id") 
     //Relation returns a list 
     //Even if we only want a single Bar object .. 
     List<Bar> bar; 

     //Getter and setter... 
    } 

Giải pháp này dường như làm việc, nhưng tôi không phải là rất tự hào về nó. Bạn nghĩ gì về nó?

Edit: Một giải pháp khác

Đạo, tôi thích rõ ràng chọn nhưng "*" thực hiện công việc :)

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

Lớp FooAndBar

public class FooAndBar { 
     @Embedded 
     Foo foo; 

     @Embedded 
     Bar bar; 

     //Getter and setter... 
    } 
+0

Nếu có xung đột giữa 'Foo' và' Bar', tôi tin rằng bạn có thể loại bỏ những điều này bằng cách tạo biểu diễn tập hợp con của lớp sau, ví dụ: 'public class BareBar {... một số trường bar ...}', và sau đó thêm 'entity = BareBar.class' vào' @ Relation'. Xem: https://developer.android.com/reference/android/arch/persistence/room/Relation.html – AjahnCharles

1

lựa chọn khác là chỉ cần viết POJO mới biểu diễn cấu trúc kết quả của truy vấn JOIN của bạn (mà thậm chí hỗ trợ đổi tên cột để tránh xung đột):

@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; 
    } 
}  

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

+1

Điều này hoạt động khi các trường có cùng tên, chỉ cần có bí danh cho chúng. –