【发布时间】:2021-05-07 18:45:35
【问题描述】:
我正在创建一个简单的应用程序来练习使用数据库。该应用程序有播放列表和歌曲。每个播放列表包含许多歌曲,并且每首歌曲可以在许多播放列表中。所以它需要一个多对多的关系。
我正在尝试使用 LiveData 和 Room 坚持 Android 的 Activity->ViewModel->Repository->Database 架构。
应用程序的 MainActivity 从用户那里收集两个歌曲名称和一个播放列表名称,然后在单击按钮时将它们添加到 Room 数据库中。
这是 Playlist 对象、Song 对象,以及一个用作交叉引用的额外对象 CrossRef:
播放列表类:
@Entity(tableName="playlist_table")
public class Playlist {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name="playlist_id")
private int playlistId;
private String name = "Default Playlist";
}
歌曲类:
@Entity(tableName="song_table")
public class Song {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name="song_id")
private int songId;
private String name;
}
CrossRef.class:
@Entity(tableName="cross_ref_table", primaryKeys = {"playlist_id", "song_id"})
public class CrossRef {
@ColumnInfo(index = true, name = "playlist_id")
public int playlistId;
@ColumnInfo(index = true, name = "song_id")
public int songId;
public CrossRef(int playlistId, int songId) {
this.playlistId = playlistId;
this.songId = songId;
}
}
MainActivity 从用户那里获取数据,调用 MyViewModel 插入数据
MainActivity.class:
myViewModel.insert(playlist, songs);
然后 MyViewModel 使用它的 Repository 来:
- 将播放列表插入到 playlist_table 并保存它的自动生成的 playlistId。
- 将每首歌曲插入到保存每个 songId 的 song_table 中。
- 在 cross_ref_table 中插入新行。
MyViewModel.class:
public void insert(Playlist playlist, List<Song> newSongs) {
int playlistId = (int)localRepository.insert(playlist);
int songId = 0;
for (Song song: newSongs) {
if(!songExists(song)) {
songId = (int)localRepository.insert(song);
} else {
songId = song.getSongId();
}
CrossRef crossRef = new CrossRef(playlistId, songId);
localRepository.insert(crossRef);
}
}
Repository 然后调用 Dao 来完成实际工作。 LocalRepository.class:
public long insert(Playlist playlist){
new InsertPlaylistAsyncTask(myDao).execute(playlist);
return resultId; // Once the async task is done, return the new playlistId.
}
public long insert(Song song){
new InsertSongAsyncTask(myDao).execute(song);
return resultId; // Once the async task is done, return the new songId.
}
public void insert(CrossRef crossRef){
new InsertCrossRefAsyncTask(myDao).execute(crossRef);
}
我的道:
@Insert
long insert(Playlist playlist); // returns a long value of the newly inserted playlistId.
@Insert
long insert(Song song); // returns a long value of the newly inserted songId.
@Insert
void insert(CrossRef crossRef);
我遇到的问题是获取自动生成的 ID。他们总是以 0 的形式返回!在 MyDao 中,这一行应该将 playlistId 分配给新插入的播放列表 ID,对吧?
int playlistId = (int)localRepository.insert(playlist);
但不,它始终为零。这是 Repository 中的 InsertPlaylistAsyncTask,新的 id 应该被传回 onPostExecute:
private class InsertPlaylistAsyncTask extends AsyncTask<Playlist, Void, Long> {
private MyDao myDao;
private InsertPlaylistAsyncTask(MyDao myDao){
this.myDao = myDao;
}
@Override
protected Long doInBackground(Playlist... playlists) {
long id = 0; // TODO: make this an array and return an ArrayList<Long>
for (Playlist r:playlists) {
id = myDao.insert(r);
}
return id;
}
@Override
protected void onPostExecute(Long playlistId) {
resultId = playlistId;
}
}
如果有人有很好的资源来了解更多关于插入到具有多对多关系的数据库的信息,我会全力以赴!谢谢大家。
【问题讨论】:
标签: java many-to-many android-room android-architecture-components