java - 安卓房间 : How to use embedded with a custom query

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

我有一个 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 对象上的嵌入式用户字段的字段 hasNewMusic 填充有子查询。

尝试了上面的方法,但没有用,不确定这是否是解决此问题的方法。

最佳答案

首先,SQLite 中没有 boolean 值,Room(正如我所读)将 1 和 0 INTEGER 值映射到 boolean 值的 true 和 false(参见 Hardcode Boolean Query In Room Database)。根据名称,我可以猜到 sound_time 不受 1 和 0 值的限制。因此,尝试将 sound_time 转换为它。

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

So if you have a query that returns street, latitude, longitude, Room will properly construct an Address class.

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

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

更新:

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

  1. 从帖子中删除用户字段。
  2. 将外键添加到帖子中。我将使用 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

关于java - 安卓房间 : How to use embedded with a custom query,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53536564/

相关文章:

android - 如何在Android Kotlin上增加动态布局?

java - 如何使用 Astyanax 客户端将 Cassandra 插入到复合列中?

java - 将默认值设置为丰富的:select component which has enableManualInput set to true?

java - 如果存在注释,则将接口(interface)添加到转换后的类

android - ListView 中的 ImageView 大小问题

java - 如何使 TextView 的最大行数 - 如果更多 - 可滚动

Java 正则表达式

android - 在 Android 中使用 PhoneGap 选择图像/视频

java - 如何退出java中的返回循环?

java - 在 M1 Apple Silicon 上运行时禁用 junit5 测试