I'm using ROOM for my project. But I'm having trouble for joining between tables, because the tables have a same name fields.
for example, my project has tree tables, "word" & "favorite" & "bookmark", which has a same name fields.
1- word
@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- favorite
@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- bookmark
@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
}
To create a join between the three, I defined a new type called "WordAndFavoriteAndBookmark", and used "@Embedded" (as shown below). and to fix the same field problem, I used prefix as a Thomas Fischer response
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; }
}
To create a join between these tables I have defined a new @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();
}
But again, after using the query, I encounter the error for the following code in my view(Activity or Fragment):
mWordAndFavoriteAndBookmark.getFavorite().getTime();
I think this is due to the use of Perfix, but I do not know the solution to this problem
EDITED: by Thomas Fisher answer, everything is fine. But when used "Count" or "Sum" in my query, I have problem for reading these values and I don't know how to read them.
You don't need a separate dao.
Except for one plain, "@Embedded" annotation, the other annotations have to set a prefix: @Embedded(prefix = "favorite_") and @Embedded(prefix = "bookmark_")
In your query, your selected fields have to have the prefix.
Instead of
select * from word join bookmark join favorite // pseudo code
You have to alias the fields to your prefix:
select word.*, bookmark.id as bookmark_id..., favorite.id as favorite_id... from...
This prevents the three id columns to override each other in the query. And with the prefix, the dao will expect all columns of that table to have that prefix in front of the actual column name.
Also what exact error do you get?
I'd guess there might be a NPE. That might have to do with your query. So if you can include the query as well, it would help find the issue.
To solve the "Count" or "Sum" field problem, I used the new compound data class. As below:
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; }
}
And in the query definition, in Dao class, I referred to this field:
@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();
Note that the alias column in query must have a same as the variable defined in the compound data class
来源:https://stackoverflow.com/questions/51512556/the-fields-same-name-issue-in-the-tables-when-join-tables-in-room