【问题标题】:The field's same name issue in the tables, when join tables in ROOM在ROOM中连接表时,表中的字段同名问题
【发布时间】:2018-07-25 06:53:40
【问题描述】:

我正在为我的项目使用 ROOM。但是我在表之间连接时遇到了麻烦,因为表具有相同的名称字段。

例如,我的项目有树表,“word”&“favorite”&“bookmark”,它们有相同的名称字段。

1- 字

@Entity(tableName = "word")
public class Word {

    @NonNull
    @PrimaryKey(autoGenerate = true)
    private int id;

    @NonNull
    private String title;
    private String mean;
    private String pronunciation;

    // Getter and Setter
}

2-最喜欢的

@Entity(tableName = "favorite",
    foreignKeys = @ForeignKey(
            entity = Word.class,
            parentColumns = "id",
            childColumns = "word_id",
            onDelete = CASCADE,
            onUpdate = CASCADE))
public class Favorite {

    @NonNull
    @PrimaryKey
    private int word_id;
    private long time;

    // Getter and Setter
}

3- 书签

     @Entity(tableName = "bookmark",
         primaryKeys = {"word_id", "category_id"},
         foreignKeys = {
            @ForeignKey(entity = Word.class,
                    parentColumns = "id",
                    childColumns = "word_id",
                    onDelete = CASCADE,
                    onUpdate = CASCADE)})
     public class Bookmark {
         @NonNull
         private int word_id;
         private long time;
         private int color;

        // Getter and Setter
}

为了在三者之间建立连接,我定义了一个名为“WordAndFavoriteAndBookmark”的新类型,并使用了“@Embedded”(如下所示)。 为了解决相同的字段问题,我使用 prefix 作为Thomas Fischer 响应

4- WordAndFavoriteAndBookmark

   public class WordAndFavoriteAndBookmark {
    @Embedded
    private Word word;

    @Embedded(prefix = "favorite_")
    private Favorite favorite;

    @Embedded(prefix = "bookmark_")
    private Bookmark bookmark;

    //Getter and Setter
    public Word getWord() { return word; }
    public void setWord(Word word) {this.word = word;}    
    public Favorite getFavorite() { return favorite; }    
    public void setFavorite(Favorite favorite) { this.favorite = favorite;}    
    public Bookmark getBookmark() { return bookmark;  }    
    public void setBookmark(Bookmark bookmark) { this.bookmark = bookmark; }    
    }

为了在这些表之间创建连接,我定义了一个新的 @Dao

 @Dao
public interface WordAndFavoriteAndBookmarkDao {
    @Query("SELECT word.*, favorite.time FROM word LEFT JOIN favorite " +
            "ON word.id = favorite.word_id")
    LiveData<List<WordAndFavoriteAndBookmark>> getAllWordsByFavoritesForLanguage();
    }

但同样,在使用查询后,我在视图(活动或片段)中遇到以下代码的错误:

mWordAndFavoriteAndBookmark.getFavorite().getTime();

我认为这是由于使用了Perfix,但我不知道这个问题的解决方案

已编辑: Thomas Fisher 回答,一切都很好。但是当在我的查询中使用“计数”或“总和”时,我无法读取这些值并且我不知道如何读取它们。

【问题讨论】:

    标签: android database android-room jointable


    【解决方案1】:
    1. 您不需要单独的 dao。

    2. 除了一个普通的“@Embedded”注解外,其他注解都必须设置前缀:@Embedded(prefix = "favorite_") 和@Embedded(prefix = "bookmark_")

    3. 在您的查询中,您选择的字段必须有前缀。

    而不是

    select * from word join bookmark join favorite // pseudo code
    

    您必须将字段别名为您的前缀:

    select word.*, bookmark.id as bookmark_id..., favorite.id as favorite_id... from...
    

    这可以防止三个 id 列在查询中相互覆盖。有了前缀,dao 将期望该表的所有列在实际列名前面都有该前缀。

    还有什么确切的错误?

    我猜可能有一个 NPE。这可能与您的查询有关。因此,如果您也可以包含查询,这将有助于找到问题。

    【讨论】:

    • 谢谢。根据您的描述,一切似乎都正常。但是对于 count() 这样的字段,我不知道如何访问它。 (示例查询:@Query("SELECT bookmarkCategory.id AS category_id, ... , COUNT(bookmark.category_id) AS count FROM bookmarkCategory LEFT JOIN bookmark ON bookmarkCategory.id = bookmark.category_id GROUP BY bookmarkCategory.id) LiveData> getAllBookmarkCategories();)
    • 为什么说“不需要单独的 dao”?
    • 我的应用只有一个 DAO。除非对您的组织有意义,否则没有技术理由需要更多。如果您有计算列,通常可以通过向数据类添加字段来获取它们。 Room 不知道这些列是从哪里来的。它只是将结果集中的列映射到数据类中的字段。我还没有尝试将这样一个额外的字段添加到复合数据类(使用@Embedded 包含其他数据类的类)。虽然值得一试,看看向 WordAndFavoriteAndBookmark 添加计数字段是否有效。
    【解决方案2】:

    为了解决“计数”或“总和”字段问题,我使用了新的复合数据类。 如下:

    public static class CategoryAndEssentials {
        @Embedded
        private BookmarkCategory bookmarkCategory;
    
        private int wordCount;
    
        public BookmarkCategory getBookmarkCategory() { return bookmarkCategory; }
        public void setBookmarkCategory(BookmarkCategory bookmarkCategory) { this.bookmarkCategory = bookmarkCategory;}
        public int getWordCount() { return wordCount; }
        public void setWordCount(int wordCount) { this.wordCount = wordCount; }
    }
    

    在查询定义中,在 Dao 类中,我引用了这个字段:

    @Query("SELECT " +
                "bookmarkCategory.*, " +
                "COUNT(bookmark.category_id) AS wordCount, " +
            "FROM bookmarkCategory LEFT JOIN bookmark " +
            "ON bookmarkCategory.id = bookmark.category_id " +
            "GROUP BY bookmarkCategory.id ")
    LiveData<List<EntityClassForJoinTables.CategoryAndEssentials>> getAllCategoriesAndEssentials();
    

    注意查询中的别名列必须与复合数据类中定义的变量相同

    【讨论】:

      猜你喜欢
      • 2015-04-12
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 2011-10-25
      • 2021-08-30
      相关资源
      最近更新 更多