How to query nested Embeded objects using Room Per

2020-07-03 06:20发布

问题:

Consider I have 3 classes User, Address, Location

class Address {
    public String street;
    public String state;
    public String city;

    @ColumnInfo(name = "post_code")
    public int postCode;

    @Embedded(prefix = "home_")
    public Location homeLocation;

    @Embedded(prefix = "office_")
    public Location officeLocation;
}

class Location{
     public long lat;
     public long lng;
}

@Entity
class User {
    @PrimaryKey
    public int id;

    public String firstName;

    @Embedded(prefix = "addr_")
    public Address address;
}

How should i write the query to get the users whose home location is between certain latitude and longitude boundary ?

Ex: If i want to find all users whose home location is between these two points Location1(13.135795,77.360348) & Location2(12.743639, 77.901424). My query would look something like this -

select * from User where address.homelocation.lat < :l1_latitude && address.homelocation.lat > l2_latitude && address.homelocation.lng > :l1_longitude && address.homelocation.lng < :l2_longitude

If i have to use prefix in the embedded location from my understanding, correct me if am wrong, all the fields inside address will get appended with prefix. So i can query city as addr_city and if i have to query lat inside the homeLocation then will it become addr_home_lat ?

Is nested embedded objects permitted in room database? If yes then how do i query the nested embedded objects?

Need some help here. Thank you.

回答1:

Yes "nested embedded objects" are permitted inside ROOM. You can write a User class which has an embedded Address class as which contains a embedded Location class.

Each time when an embedded object is added, room flattens out the table. In your case room generates a table called "User" with the following columns:

id, firstName, addr_street, addr_state, addr_city, addr_post_code, addr_home_lat, addr_home_lng, addr_office_lat, addr_office_lng

So your query should be like :

@Query("SELECT * FROM User WHERE " +
        "addr_home_lat BETWEEN :lat1 AND :lat2" +
        " AND addr_home_lng BETWEEN :lng1 AND :lng2")
List<User> findInRange(long lat1, long lat2, long lng1, long lng2);

Notice that "lat" has been flattened to "addr_home_lat" and "lng" to "addr_home_lng". So you can use these column names for applying the filter logic.

In case you misspelled a column name for example "home_lng" instead of "addr_home_lng", then room will find that out and give you an error :

There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: home_lng)

For more information on room database, check out the Google I/O talk.



回答2:

Yes, you can use nested embedded objects in room library. Please follow the post Room Persistence.