![](/img/trans.png)
[英]Android Room: FOREIGN KEY constraint failed (Sqlite code 787)
[英]Android room FOREIGN KEY constraint failed even though values are the same
android 上的 ROOM 数据库拒绝使用外键正常工作,并且无论我尝试如何修复它,总是出错。
我正在尝试将播放列表存储到 Room 数据库中。 所以 playlistdb 包含与播放列表关联的专辑封面、名称和 ID。 Songsdb 包含有关歌曲的所有信息(URI、专辑封面、标题、艺术家和 playlist_id(外键))
忽略凌乱的 WIP 代码,但是,我尝试按照以下方法解决标题中描述的问题:
创建单独的键而不使用父表的自动生成的主键
硬编码值
添加日志条目以获取我要插入数据库的值
但无济于事。
问题在于在下面的 insertPlaylists function 中插入子表的代码。
Playlists.java(父)(部分)
@Entity(indices = {@Index(value = {"id"}, unique = true) }, tableName = "playlists")
public class Playlists {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "index")
public int index;
@ColumnInfo(name = "id")
public int id;
@ColumnInfo(name = "name")
private String playlistName;
//this is the associated album art with the playlist, will belong to the first song.
@ColumnInfo(name = "album_art")
private String albumArt;
歌曲的一部分。java(儿童)
@Entity(foreignKeys = {
@ForeignKey(entity = Playlists.class,
parentColumns = "id",
childColumns = "playlist_id",
onDelete = ForeignKey.CASCADE)},
tableName = "songs",
indices = @Index(value = "playlist_id"))
public class Songs {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "index")
private int index;
@ColumnInfo(name = "playlist_id")
private int playlistID;
@ColumnInfo(name = "song_id")
private String songId;
@ColumnInfo(name = "title")
private String title;
@ColumnInfo(name = "album")
private String album;
@ColumnInfo(name = "artist")
private String artist;
//String can always be converted into URI
//use String in database for consistency
@ColumnInfo(name = "album_art")
private String albumArt;
@ColumnInfo(name = "duration")
private String duration;
Function 插入播放列表:
public static void insertPlaylist(Context context, Playlists playlist, SongData[] songs){
SongsDB songsDB;
PlaylistsDB playlistsDB;
songsDB = SongsDB.getInstance(context);
playlistsDB = PlaylistsDB.getInstance(context);
int index = 0;
//insert playlists first
//get index from playlists so we can increment the value here to give it a unique value.
index = playlistsDB.playlistsDao().queryLastInsert();
//increment index
index++;
playlist.setPlaylistID(index);
playlistsDB.playlistsDao().insertPlaylist(playlist);
//log for sanity check
Log.e("tesststaAETAST:", Integer.toString(playlistsDB.playlistsDao().queryLastInsert()));
Log.e("INDEX:", Integer.toString(index));
//then insert songs
for(int i =0; i < songs.length; i++)
{
Songs song = new Songs(0,songs[i].getSongId(),songs[i].getTitle(),songs[i].getAlbum(),songs[i].getArtist(),songs[i].getAlbumArt().toString(),songs[i].getDuration(), index);
songsDB.songsDao().insertPlaylist(song);
}
SongsDB.destroyInstance();
PlaylistsDB.destroyInstance();
}
播放列表道:
@Dao
public interface PlaylistsDao {
@Query("SELECT * from playlists")
Cursor queryPlaylists();
@Query("SELECT id from playlists WHERE name like :name")
Cursor queryPlaylistID(String name);
//return 0 if max returns null when table is empty
@Query("SELECT COALESCE(MAX(id), 0)from playlists")
int queryLastInsert();
@Insert()
void insertPlaylist(Playlists playlists);
@Update()
void updatePlaylist(Playlists playlists);
@Delete()
void deletePlaylist(Playlists playlists);
@Query("DELETE FROM playlists WHERE id = :id")
void deletePlaylistByID(int id);
@Query("DELETE FROM playlists")
void resetPlaylist();
}
宋道:
@Dao
public interface SongsDao {
@Query("SELECT playlist_id from songs")
Cursor queryPlaylists();
@Query("SELECT * from Songs WHERE playlist_id like :playlistID")
Cursor querySongsFromPlaylist(int playlistID);
@Insert()
void insertPlaylist(Songs songs);
@Update()
void updatePlaylist(Songs songs);
@Delete()
void deletePlaylist(Songs songs);
@Query("DELETE FROM Songs")
void resetPlaylist();
}
正如您从日志输出中看到的那样,插入索引的值(对应于 playlist_id)与我刚刚从数据库中查询的值完全相同。
2019-10-03 18:58:59.538 16084-16084/com.lucas.darkplayer E/tesststaAETAST:: 3
2019-10-03 18:58:59.538 16084-16084/com.lucas.darkplayer E/INDEX:: 3
您所做的一切似乎都很好,但您不应该有两个单独的Playlist
和Song
数据库。 相反,您应该只有一个包含两个表(实体)的数据库,它们应该通过FOREIGN KEY CONSTRAINT
相互关联。
我发现的另一件事是,您的Playlist
实体中有两列似乎具有相同的目的: index
(您定义为自动生成的 PrimaryKey)和id
。 我不确定你为什么这样做,但我认为你应该只有一个名为id
的列并将该字段PRIMARY KEY
。
此外,如果您将 PrimaryKey 定义为autogenerate = true
,则无需担心生成唯一的 id 值。 相反,当您第一次在数据库中保存实体实例时,数据库会自动为您处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.