【问题标题】:andorid room inner join one column from tableandroid房间内部从表中加入一列
【发布时间】:2020-05-20 11:30:30
【问题描述】:

这是我的桌子:

@Parcelize
@Entity(tableName = "profile")
data class Profile(
    @SerializedName("id") @PrimaryKey var id:Long,
    @SerializedName("name") var name :String?,
    @TypeConverters(UserConverter::class)
    @NotNull
    @SerializedName("users") var users :List<Long>?
):Parcelable

这是我的第二张桌子:

@Parcelize
@Entity(tableName = "user")
data class User(
    @PrimaryKey
    @SerializedName("id") var id: Long,
    @SerializedName("name") var name: String
) : Parcelable

我想得到这个对象:

data class ProfileWithUsersName(
    val profile: Profile,
    val usersName: List<String>?
)

为了得到这个对象列表,我这样做:

fun getProfiles() :List<ProfileWithUsersName>{
    val arrayListTemp = arrayListOf<ProfileWithUsersName>()
    val profiles =  profileDao.getProfiles()
    for(profile in profiles){
        if(profile.users != null) {
            arrayListTemp.add(
                ProfileWithUsersName(
                    profile,
                    userDao.getUsersNameByIds(profile.users!!)
                )
            )
        }else{
            ProfileWithUsersName(
                profile,
                null
            )
        }
    }
    return arrayListTemp.toList()
}

对一个查询执行此操作是否有任何更改?

【问题讨论】:

  • 如何使用join?你可以关注this
  • @KasımÖzdemir 我没有关系表
  • 我解释了如何连接有关系和没有关系的表
  • @KasımÖzdemir 我不明白我该怎么做

标签: android android-room


【解决方案1】:

可能是这样的

@Dao
abstract class ProfileDao {

    companion object {
        const val QUERY = "SELECT * FROM profile " +
                "INNER JOIN user " +
                `your condition`
    }

    @Query(QUERY)
    abstract fun getCurrentStep(): List<ProfileWithUsersName>?
    }
}

你的个人资料应该是这样的

data class ProfileWithUsersName(
        @Embedded val profile: Profile,
        @Embedded val usersName: List<String>?
)

【讨论】:

  • Kostya 我这样做了:@Query("SELECT * from profile inner join user WHERE user.id in profile.user") 有趣的 getProfiles2() 但我的项目没有构建
  • 您可以发送错误消息吗?你的情况应该是这样的INNER JOIN table2 ON table1.column_name = table2.column_name;
  • org.gradle.api.tasks.TaskExecutionException:任务“:app:kaptDebugKotlin”执行失败。在 org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.accept(ExecuteActionsTaskExecuter.java:151) 在 org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.accept(ExecuteActionsTaskExecuter.java:148) 在 org .gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:191) 在 org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:141)
  • 执行 org.jetbrains.kotlin.gradle.internal.KaptExecution 时发生故障
  • 那么查询应该是什么样子?
【解决方案2】:

这可能不是完整的答案,但为什么不得到部分答案?

表格结构注释

  • 这不是最理想的,最好不要在 Profile 类中保存有关具有确切配置文件的用户的信息(更好的选择 - 将其删除到另一个表中)。但顺其自然吧。
  • 在不更改表结构的情况下,我认为如果您只调用一次函数“userDao.getUsersNameByIds(profile.users!!)”,您对嵌套查询的决定可能会更好(但为此您应该稍微更改逻辑)。但我认为您的表格不会太大,无法将时间投入到此类优化中。

至于“在一个查询中执行此操作”

  • 实际上,我认为有一些成功的机会,但老实说,我认为这不值得,而且查询会比循环更快或更优雅。但这对某人来说可能是一个挑战:)

  • 这里的主要问题是实体“个人资料”中的“用户”字段。在 SQLite 中,我猜你将它保存为字符串(在 UserConverter 的帮助下)。例如,如果您在 SQLite 中有 id 列表:[111,222,333],它们将被保存为 TEXT "111,222,333"。因此,在下一步中,我们必须以某种方式将具有这样一个字段的表连接到一个具有 INTEGERS 111|222|333 的表中。

  • 这只能通过将 INTEGER 转换为 TEXT 然后在条件下加入表来完成 - casted_value_from_second_table LIKE ["%," + value_from_first_table + ",%]" 在伪代码中。也许这需要对您的 TypeConverter 进行一些更改。即使成功,使用“LIKE”连接表也不是最佳做法。

结论

  • 如果不更改表格结构,并且如果您的表格不是很大,我认为您现在的做法是可以接受的。使用“一个查询”(同样,不更改数据库表的结构)这不是常规任务,有几个问题需要通过实验解决 - 我认为不值得。

附:也许我没有看到什么明显的决定,所以这只是我个人的看法:)

【讨论】:

    猜你喜欢
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 2014-07-18
    相关资源
    最近更新 更多