【问题标题】:Android Room: How to use embedded with a custom queryAndroid Room:如何使用嵌入的自定义查询
【发布时间】:2019-05-01 08:54:44
【问题描述】:

我有一个 PostDAO,看起来像这样。

@Dao
public interface PostDAO extends DAOTemplate<Post> {
    @Query("SELECT * FROM posts order by time DESC")
    LiveData<List<Post>> getPosts();
}

还有 Post Pojo。

@Keep
@Entity(tableName = "posts")
open class Post : Serializable, Cloneable {
    @NonNull
    @PrimaryKey
    var id: String? = null

    var text: String? = null

    var time: Long = 0
    var uid: String? = null
    @Embedded
    var user: User? = null

    public override fun clone(): Post {
        return super.clone() as Post
    }
}

如您所见,User 对象是 @Embedded

和用户的 DAO

@Dao
public interface UserDAO extends DAOTemplate<User> {
@Query("SELECT *,(SELECT sound_time FROM sounds WHERE sound_uid =:id AND " +
                "(sound_time < strftime('%s', 'now'))) AS hasNewMusic    " +
                "FROM users WHERE user_uid = :id")
        LiveData<User> getUser(String id);
}

和用户 Pojo

@Keep
@IgnoreExtraProperties
@Entity(tableName = "users")
class User : ModelTemplate() {
    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "user_uid")
    override var id: String? = null;

    var name: String? = null
    var icon: String? = null

    var hasNewMusic: Boolean = false
}

现在,我希望 Post 对象上的 Embedded user 字段在 hasNewMusic 字段中填充子查询。

尝试了上述方法,但无法正常工作,并且不确定这是否可以解决。

【问题讨论】:

    标签: java android kotlin android-room android-architecture-components


    【解决方案1】:

    首先,SQLite 中没有布尔值,Room(如我所读)将 1 和 0 INTEGER 值映射到布尔值的真假(参见Hardcode Boolean Query In Room Database)。从名字上我可以猜到sound_time 不受 1 和 0 值的限制。因此,尝试将sound_time 转换为它。

    另外,我认为您误用了@Embedded 注释。它用于将一个表的列放入可以通过某种原因进行分组的类中。例如这里 (@Embedded) 是这样写的:

    因此,如果您的查询返回街道、纬度、经度、房间 将正确地构造一个 Address 类。

    因此,您应该修改 PostDAO::getPosts() 方法以返回用户的列,通过 INNER JOIN 加上您的巨大选择。而且我不保证这会奏效,因为我没有这样做。由于某些原因,它也很糟糕。

    或者您可以在没有用户字段的情况下保留 Post,并创建一个名为 PostWithUser 的实体并使用 @Relation 注释。哪个更好,在文档中推荐。

    UPD:

    要获取两个实体,试试这个:

    1. 从帖子中删除用户字段。
    2. 在 Post 中添加外键。我将使用userId,如果uid 已经用于 而是使用它:

      @Entity(tableName = "posts",
              foreignKeys = [ForeignKey(
                      entity = Post::class,
                      parentColumns = ["user_id"], //from ColumnInfo of User class
                      childColumns = ["userId"],
                      onDelete = CASCADE)],
              indices = [Index(value = ["userId"]]))
      class Post {
      
          @PrimaryKey
          var id: String? = null
      
          var userId: String? = null
      
          //...else code....
      
      }
      
    3. 创建 PostWithUser 类:

      class PostWithUser {
          @Embedded lateinit var post: Post
          @Embedded lateinit var user: User 
      }
      
    4. 制作 PostWithUserDao:

      class PostWithUserDao {
          @Query("select * from post, user where post.userId = user.user_id")
          fun getPostsWithUsers(): List<PostWithUser>
      }
      

    由于我没有设法在此处放置 sound_time 子查询,因此我会在第二个查询中进行,但如果您弄清楚该怎么做,我认为它可以工作。

    另见:Room database with one-to-one relation

    【讨论】:

    • 至于关系,不要认为这会在这里起作用,因为一对多
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多