Android:房间库中的多对多关系(sqllite)

时间:2018-01-29 12:30:22

标签: android android-sqlite android-room

我有一个媒体播放器应用程序,其中“Song”为实体,“Playlist”为实体。每首歌曲可以在多个播放列表中,每个播放列表包含许多歌曲。我正在使用Room库作为我的sqlite数据库管理器。任何建议如何实现这种多对多的关系?我没有在文档中找到如何在Room上实现多对多关系的示例。

3 个答案:

答案 0 :(得分:2)

在Room中实现多对多关系与实现与任何SQL数据库的多对多关系没有什么不同:有一个连接表。对于Room,该连接表是通过连接@Entity创建的。

来自earlier question from you

This sample project说明了这项技术。

我有一个Category类,碰巧实现了树结构(父类和子类之间的1:N关系):

@Entity(
  tableName="categories",
  foreignKeys=@ForeignKey(
    entity=Category.class,
    parentColumns="id",
    childColumns="parentId",
    onDelete=CASCADE),
  indices=@Index(value="parentId"))
public class Category {
  @PrimaryKey
  @NonNull
  public final String id;
  public final String title;
  public final String parentId;

  @Ignore
  public Category(String title) {
    this(title, null);
  }

  @Ignore
  public Category(String title, String parentId) {
    this(UUID.randomUUID().toString(), title, parentId);
  }

  public Category(String id, String title, String parentId) {
    this.id=id;
    this.title=title;
    this.parentId=parentId;
  }
}

并且,我有一个Customer,其中嵌套CategoryJoin代表客户和类别之间的M:N关系:

@Entity(indices={@Index(value="postalCode", unique=true)})
class Customer {
  @PrimaryKey
  @NonNull
  public final String id;

  public final String postalCode;
  public final String displayName;
  public final Date creationDate;

  @Embedded
  public final LocationColumns officeLocation;

  public final Set<String> tags;

  @Ignore
  Customer(String postalCode, String displayName, LocationColumns officeLocation,
           Set<String> tags) {
    this(UUID.randomUUID().toString(), postalCode, displayName, new Date(),
      officeLocation, tags);
  }

  Customer(String id, String postalCode, String displayName, Date creationDate,
           LocationColumns officeLocation, Set<String> tags) {
    this.id=id;
    this.postalCode=postalCode;
    this.displayName=displayName;
    this.creationDate=creationDate;
    this.officeLocation=officeLocation;
    this.tags=tags;
  }

  @Entity(
    tableName="customer_category_join",
    primaryKeys={"categoryId", "customerId"},
    foreignKeys={
      @ForeignKey(
        entity=Category.class,
        parentColumns="id",
        childColumns="categoryId",
        onDelete=CASCADE),
      @ForeignKey(
        entity=Customer.class,
        parentColumns="id",
        childColumns="customerId",
        onDelete=CASCADE)},
    indices={
      @Index(value="categoryId"),
      @Index(value="customerId")
    }
  )
  public static class CategoryJoin {
    @NonNull public final String categoryId;
    @NonNull public final String customerId;

    public CategoryJoin(String categoryId, String customerId) {
      this.categoryId=categoryId;
      this.customerId=customerId;
    }
  }
}

您的@Dao具有根据关系检索对象的方法,例如:

  @Query("SELECT categories.* FROM categories\n"+
    "INNER JOIN customer_category_join ON categories.id=customer_category_join.categoryId\n"+
    "WHERE customer_category_join.customerId=:customerId")
  List<Category> categoriesForCustomer(String customerId);

  @Query("SELECT Customer.* FROM Customer\n"+
    "INNER JOIN customer_category_join ON Customer.id=customer_category_join.customerId\n"+
    "WHERE customer_category_join.categoryId=:categoryId")
  List<Customer> customersForCategory(String categoryId);

答案 1 :(得分:1)

您需要创建3个表:

  1. 歌曲(song_id,song_name,艺术家)

  2. 播放列表(playlist_id,playlist_name)

  3. 联结表(playlist_id,song_id)

  4. 参考链接:

    Many-to-Many relation exmples

答案 2 :(得分:0)

您需要创建一个代表“属于”关系的新“联结”类。在房间里,它是这样的:

@Entity(tableName = "playlist_entries",
    primaryKeys = { "songId", "playlistId" },
    foreignKeys = {
            @ForeignKey(entity = Song.class,
                        parentColumns = "id",
                        childColumns = "songId"),
            @ForeignKey(entity = Playlist.class,
                        parentColumns = "id",
                        childColumns = "playlistId")
            })
public class PlaylistEntry {
    public final int songId;
    public final int playlistId;

    public PlaylistEntry(final int songId, final int playlistId {
        this.songId = songId;
        this.playlistId = playlistId;
    }
}