jjzjj

android - 与 Room 和 LiveData 的多对多关系

coder 2023-12-20 原文

我有一个 rest api,它返回一个地点列表,其中有一个类别列表:

{
      "id": "35fds-45sdgk-fsd87",
      "name" : "My awesome place",
       "categories" : [
          {
            "id": "cat1",
            "name" : "Category 1"
          },
          {
            "id": "cat2",
            "name" : "Category 2"
          },
          {
            "id": "cat3",
            "name" : "Category 3"
          }
       ]
}

所以使用改造我从远程服务器获得这些模型类:

data class Category(var id: String, var name: String)

data class Place(
  var id: String,
  var name: String,
  var categories: List<Category>
)

问题是——我希望 viewModel 总是从返回 Flowables 的本地 Room 数据库中检索,并且只触发刷新操作来更新数据库,从而更新 View 。

DAO 方法示例:

@Query("select * from Places where placeId = :id")
fun getPlace(id: String): Flowable<Place>

所以我尝试像这样对这两个类建模:

@Entity
data class Category(var id: String, var name: String)


@Entity
data class Place(
  @PrimaryKey
  var id: String,
  var name: String,
  var categories: List<Category>
)

当然,Room 无法自行处理关系。我看过this post它只是从本地数据库中检索以前的城市列表,但这种情况与那个不匹配。

我能想到的唯一选择是将数据库中的类别保存为 JSON 字符串,但这会失去数据库的关系质量...

这似乎是一个很常见的用例,但我还没有找到太多关于它的信息。

最佳答案

在 Room 中可以有多对多的关系。

首先将@Ignore 注释添加到您的Place 类。它会告诉 Room 忽略此属性,因为它无法在没有转换器的情况下保存对象列表。

data class Category(
        @PrimaryKey var id: String, 
        var name: String
)

data class Place(
        @PrimaryKey var id: String,
        var name: String,
        @Ignore var categories: List<Category>
) 

然后创建一个类来表示这两个类之间的联系。

@Entity(primaryKeys = ["place_id", "category_id"],
        indices = [
            Index(value = ["place_id"]),
            Index(value = ["category_id"])
        ],
        foreignKeys = [
            ForeignKey(entity = Place::class,
                    parentColumns = ["id"],
                    childColumns = ["place_id"]),
            ForeignKey(entity = Category::class,
                    parentColumns = ["id"],
                    childColumns = ["category_id"])
        ])
data class CategoryPlaceJoin(
        @ColumnInfo(name = "place_id") val placeId: String,
        @ColumnInfo(name = "category_id") val categoryId: String
)

如您所见,我使用了外键。

现在您可以指定特殊的 DAO 来获取地点的类别列表。

@Dao
interface PlaceCategoryJoinDao {

    @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
    @Query("""
        SELECT * FROM category INNER JOIN placeCategoryJoin ON
        category.id = placeCategoryJoin.category_id WHERE
        placeCategoryJoin.place_id = :placeId
        """)
    fun getCategoriesWithPlaceId(placeId: String): List<Category>

    @Insert
    fun insert(join: PlaceCategoryJoin)
}

最后一件重要的事情是每次插入新的 Place 时都插入连接对象。

val id = placeDao().insert(place)
for (place in place.categories) {
   val join = CategoryPlaceJoin(id, category.id)
   placeCategoryJoinDao().insert(join)
}

现在,当您从 placeDao() 获取地点时,它们的类别列表为空。为了添加类别,您可以使用这部分代码:

fun getPlaces(): Flowable<List<Place>> {
    return placeDao().getAll()
            .map { it.map { place -> addCategoriesToPlace(place) } }
}

private fun addCategoriesToPlace(place: Place): Place {
    place.categories = placeCategoryJoinDao().getCategoriesWithPlaceId(place.id)
    return place
}

要查看更多详细信息,请参阅 this article .

关于android - 与 Room 和 LiveData 的多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50799324/

有关android - 与 Room 和 LiveData 的多对多关系的更多相关文章

  1. ruby - Rails 关联 - 同一个类的多个 has_one 关系 - 2

    我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下

  2. [工业相机] 分辨率、精度和公差之间的关系 - 2

    📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

  3. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  4. ruby - Rails 组合多个 activerecord 关系 - 2

    我想合并多个事件记录关系例如,apple_companies=Company.where("namelike?","%apple%")banana_companies=Company.where("namelike?","%banana%")我想结合这两个关系。不是合并,合并是apple_companies.merge(banana_companies)=>Company.where("namelike?andnamelike?","%apple%","%banana%")我要Company.where("名字像?还是名字像?","%apple%","%banana%")之后,我会写代

  5. ruby-on-rails - Ruby on Rails - has_one 关系,如何检查它是否具有现有关联? - 2

    我有一个简单的问题,与关联有关。我有一个书的模型,它有_onereservation。预订属于_书本。我想在预订Controller的创建方法中确保在预订时没有预订一本书。换句话说,我需要检查该书是否存在任何其他预订。我该怎么做?编辑:Aaa我做到了,感谢大家的提示,学到了一些新东西。当我尝试提供的解决方案时,出现no_method错误或nil_class等。这让我开始思考,我尝试处理的对象根本不存在。Krule给了我使用book.find的想法,所以我尝试使用它。最终我得到了它的工作:book=Book.find_by_id(reservation_params[:book_id])

  6. ruby-on-rails - Ruby/Rails - 检查 HABTM 关系记录中是否存在子 ID - 2

    我有一组名为Tasks和Posts的资源,它们之间存在has_and_belongs_to_many(HABTM)关系。还有一个连接它们的值的连接表。create_table'posts_tasks',:id=>falsedo|t|t.column:post_id,:integert.column:task_id,:integerend所以我的问题是如何检查特定任务的ID是否存在于从@post.tasks创建的数组中?irb(main):011:0>@post=Post.find(1)=>#@post.tasks=>[#,#]所以我的问题是,@post.tasks中是否存在"@task

  7. Ruby On Rails 模型、 View 和 Controller 之间的关系 - 2

    根据我目前的理解,如果我必须描述Rails应用程序的各个组件如何协同工作以响应请求,我会说以下内容:1)路由确定哪些请求URL映射到哪些Controller方法。2)Controller方法从模型中获取信息并将该信息(以全局变量的形式)传递给相应的View模板。3)View模板使用存储在全局变量中的数据来构造最终响应。在上面的解释中,几个组件之间的关系是明确的,不可否认的;即:1)路由和Controller方法2)Controller方法和View模板其实上面的关系是一对一的。但是,模型类与其相邻组件类型(即Controller)的关系并不明确。是的,Controller从模型中检索信

  8. ruby-on-rails - 本地 gem 的“bundle 安装”没有解决依赖关系,而 'gem install' 可以 - 2

    我在目录“/home/enterprise/pkg”中有一个本地gem(enterprise-0.0.1.gem)。它依赖于active_directorygem(v1.5.5),这是在它的enterprise.gemspec文件中指定的,如下所示:-gem.add_dependency("active_directory")在我的应用程序的Gemfile中,我添加了以下行:-gem'enterprise','0.0.1',path=>'/home/enterprise/pkg'当我做的时候bundleinstall在我的应用程序的源目录中,只安装了企业gem。因此,我遇到了引用act

  9. ruby-on-rails - 如何添加具有额外列的多对多记录 - 2

    我有以下模型用户has_many:users_contactshas_many:contacts,through::users_contactsaccepts_nested_attributes_for:contacts,allow_destroy:true联系方式has_many:users_contactshas_many:users,through::users_contactsaccepts_nested_attributes_for:users_contacts,allow_destroy:true用户联系belongs_to:usersbelongs_to:contacts

  10. ruby-on-rails - Rails/Mongoid 与 Struct 的关系问题 - 2

    我正在构建这个图书馆应用程序,它有3个类。国家、图书馆和书籍。国家有许多图书馆,图书馆属于一个国家。图书馆有很多书,书是嵌入图书馆的。但是,当我执行此auto_pick_job时,我们到达top_free_book并调用library.state。由于某种原因,library.state为nil。我希望恢复状态但没有骰子。我调用和创建库的方式如下。所以图书馆将永远属于一个现有的国家。state=Stats.find(x)library=state.libaries.new(info)library.save_optimistic!我也很感激使用Struct的关系帮助。classStat

随机推荐