使用 Android Room 从 Junction Table 获取数据
Posted
技术标签:
【中文标题】使用 Android Room 从 Junction Table 获取数据【英文标题】:Get data from Junction Table with Android Room 【发布时间】:2020-06-03 16:53:30 【问题描述】:我目前正在构建一个 android 应用程序,该应用程序显示一个由多个航路点构成的路线。我已经计划好了数据库模式(chen-notation [可能无效的“语法”]):
我尝试重新创建与 android room 的 n-m 关系,但我不知道如何检索联结表 (route_waypoint) 的 index_of_route
属性。
当我得到这样的数据时,我想要联结表属性index_of_route
:
@Transaction
@Query("SELECT * FROM POIRoute")
List<RouteWithWaypoints> getRoutes();
在 POIWaypoint 类中(可能作为额外属性),或者至少可以从另一个类可以访问,可能是这样实现的:
@Embedded
POIWaypoint waypoint;
int indexOfRoute;
目前我没有从联结表中获得indexOfRoute
属性。
我已经创建的课程:
RouteWithWaypoints:
public class RouteWithWaypoints
@Embedded
private POIRoute poiRoute;
@Relation(parentColumn = "id",entityColumn = "id",associateBy = @Junction(value = RouteWaypoint.class, parentColumn = "routeId", entityColumn = "waypointId"))
private List<POIWaypoint> waypoints;
public POIRoute getPoiRoute()
return poiRoute;
public void setPoiRoute(POIRoute poiRoute)
this.poiRoute = poiRoute;
public List<POIWaypoint> getWaypoints()
return waypoints;
public void setWaypoints(List<POIWaypoint> waypoints)
this.waypoints = waypoints;
RouteWaypoint:
@Entity(primaryKeys = "waypointId", "routeId", foreignKeys =
@ForeignKey(entity = POIWaypoint.class, parentColumns = "id", childColumns = "waypointId"),
@ForeignKey(entity = POIRoute.class, parentColumns = "id", childColumns = "routeId")
)
public class RouteWaypoint
private int waypointId;
private int routeId;
// I want this attribute inside the POIWaypoint class
@ColumnInfo(name = "index_of_route")
private int indexOfRoute;
public int getWaypointId()
return waypointId;
public void setWaypointId(int waypointId)
this.waypointId = waypointId;
public int getRouteId()
return routeId;
public void setRouteId(int routeId)
this.routeId = routeId;
POI路线:
@Entity
public class POIRoute
private String name;
private String description;
@PrimaryKey(autoGenerate = true)
private int id;
private boolean user_generated;
private int parentId;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getDescription()
return description;
public void setDescription(String description)
this.description = description;
public int getId()
return id;
public void setId(int id)
this.id = id;
public boolean isUser_generated()
return user_generated;
public void setUser_generated(boolean user_generated)
this.user_generated = user_generated;
public int getParentId()
return parentId;
public void setParentId(int parentId)
this.parentId = parentId;
POIWaypoint(请忽略未完成的位置属性):
@Entity
public class POIWaypoint
@PrimaryKey(autoGenerate = true)
private long id;
@ColumnInfo(name = "long_description")
private String longDescription;
private String title;
@ColumnInfo(name = "short_description")
private String shortDescription;
// use converter: https://developer.android.com/training/data-storage/room/referencing-data
@Ignore
private GeoPoint position;
public long getId()
return id;
public void setId(long id)
this.id = id;
public GeoPoint getPosition()
return position;
public void setPosition(GeoPoint position)
this.position = position;
public String getTitle()
return title;
public void setTitle(String title)
this.title = title;
public String getShortDescription()
return shortDescription;
public void setShortDescription(String shortDescription)
this.shortDescription = shortDescription;
public String getLongDescription()
return longDescription;
public void setLongDescription(String longDescription)
this.longDescription = longDescription;
【问题讨论】:
看来你做得很好。但是你的问题到底是什么?您没有在 RouteWithWaypoints 中获得一些字段,是吗?不清楚 编辑了我的帖子以更具体地说明我的问题和我想要完成的事情。简而言之:目前我无法访问联结表中的index_of_waypoint
属性。在最好的情况下,当我得到一个 RouteWithWaypoints
的实例时,我希望 index_of_waypoint
在 POIWaypoint
类中。
我认为你正在朝着正确的方向前进,你应该在实践中尝试你的想法。但我有一个猜测,因为房间里的关系不是很通用的工具,如果你的想法失败了,你应该记住,你可以用普通的旧 SQL 和循环做你想做的一切)
【参考方案1】:
我通过自己管理关系解决了我的问题。我将 RouteDao 更改为抽象类以插入我自己的方法,该方法自己管理部分联结表:
RouteDao:
private RouteDatabase database;
public RouteDao(RouteDatabase database)
this.database = database;
@Query("Select * from POIRoute")
public abstract List<POIRoute> getRoutes();
@Query("SELECT * FROM POIRoute WHERE id = :id")
public abstract POIRoute getRoute(int id);
@Insert
abstract void insertRouteWithWaypoints(RouteWithWaypoints routeWithWaypoints);
public List<RouteWithWaypoints> getRoutesWithWaypoints()
List<POIRoute> routes = this.getRoutes();
List<RouteWithWaypoints> routesWithWaypoints = new LinkedList<>();
for (POIRoute r : routes)
routesWithWaypoints.add(new RouteWithWaypoints(r, database.wayPointDao().getWaypointsFromRoute(r.getId())));
return routesWithWaypoints;
public RouteWithWaypoints getRouteWithWaypoints(int id)
POIRoute route = this.getRoute(id);
RouteWithWaypoints routeWithWaypoints = null;
if (route != null)
routeWithWaypoints = new RouteWithWaypoints(route, database.wayPointDao().getWaypointsFromRoute(route.getId()));
return routeWithWaypoints;
路点道:
@Query("SELECT * FROM POIWaypoint")
POIWaypoint getWaypoints();
@Query("SELECT * FROM POIWaypoint WHERE id = :id")
POIWaypoint getWaypoint(long id);
@Query("SELECT pw.*, rw.index_of_route as 'index' FROM POIWaypoint as pw Join RouteWaypoint as rw on (rw.waypointId = pw.id) where rw.routeId = :id order by 'index' ASC")
List<POIRouteStep> getWaypointsFromRoute(int id);
【讨论】:
干得好。仍然有一些未来优化的领域,因为您在getRoutesWithWaypoints
方法中的循环内进行数据库调用(通常这不是最佳选择)。以上是关于使用 Android Room 从 Junction Table 获取数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Android Room 从数据库中获取一行? [复制]
Android Jetpack 从使用到源码深耕数据库注解Room 从实践到原理
从 SQLite 迁移到 Android Room Persistence Library